main.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // This example shows the resolution of a 3D magnetodynamic problem of magnetic induction using the
  2. // so called a-v formulation. An aluminium tube is surrounded by 5 turns of a thick copper wire (1cm radius).
  3. // Because of the alternating voltage (50 Hz) applied to the ends of the wire, eddy currents appear
  4. // in the conducting aluminium tube. In this example the skin effect in the thick wire can also be observed.
  5. //
  6. // In order to remove the singularity (that comes from the magnetic equations) in the generated algebraic matrix
  7. // a gauge condition is used. For that a spanning tree is created on the whole mesh, starting the growth on the
  8. // region where the magnetic potential vector field 'a' will be constrained (here the domain boundary).
  9. //
  10. // This example was adapted from, and validated with an example developed for the GetDP
  11. // software (Patrick Dular and Christophe Geuzaine).
  12. #include "sparselizardbase.h"
  13. using namespace mathop;
  14. void sparselizard(void)
  15. {
  16. // The domain regions as defined in 'inductionheating.geo':
  17. int coil = 1, tube = 2, air = 3, coilskin = 4, tubeskin = 5, vin = 6, vout = 7, domainboundary = 8;
  18. // Load the mesh file. It can include curved elements.
  19. mesh mymesh("inductionheating.msh");
  20. // Define extra regions for convenience:
  21. int conductor = regionunion({coil,tube});
  22. int wholedomain = regionunion({conductor,air});
  23. domainboundary = regionunion({domainboundary,vin,vout});
  24. parameter mu, sigma;
  25. // Define the magnetic permeability mu [H/m] everywhere (the materials here are not magnetic):
  26. mu|wholedomain = 4*getpi()*1e-7;
  27. // Conductivity of the copper coil and aluminium tube [S/m]:
  28. sigma|coil = 6e7;
  29. sigma|tube = 3e7;
  30. // Set the working frequency to 50 Hz:
  31. setfundamentalfrequency(50);
  32. // Define a spanning tree to gauge the magnetic vector potential (otherwise the matrix to invert is singular).
  33. // Start growing the tree from the regions with constrained potential vector (here the domain boundary):
  34. spanningtree spantree({domainboundary});
  35. // Use nodal shape functions 'h1' for the electric scalar potential 'v'.
  36. // Use edge shape functions 'hcurl' for the magnetic vector potential 'a'.
  37. // A spanning tree has to be provided to field 'a' for gauging.
  38. // Since the solution has a component in phase with the electric actuation
  39. // and a quadrature component we need 2 harmonics at 50Hz
  40. // (harmonic 1 is DC, 2 is sine at 50Hz and 3 cosine at 50Hz).
  41. field a("hcurl", {2,3}, spantree), v("h1", {2,3});
  42. // Gauge the vector potential field on the whole volume:
  43. a.setgauge(wholedomain);
  44. // Select adapted interpolation orders for field a and v:
  45. a.setorder(wholedomain, 0);
  46. v.setorder(wholedomain, 1);
  47. // Put a magnetic wall (i.e. set field a to 0) all around the domain (no magnetic flux can cross it):
  48. a.setconstraint(domainboundary);
  49. // Also ground v on face 'vout':
  50. v.setconstraint(vout);
  51. // Set v to 1V on face 'vin' for the in-phase component and to 0 for the quadrature component:
  52. v.harmonic(2).setconstraint(vin, 1);
  53. v.harmonic(3).setconstraint(vin);
  54. // Define the weak magnetodynamic formulation:
  55. formulation magdyn;
  56. // The strong form of the magnetodynamic a-v formulation is
  57. //
  58. // curl( 1/mu * curl(a) ) + sigma * (dt(a) + grad(v)) = js, with b = curl(a) and e = -dt(a) - grad(v)
  59. //
  60. // Magnetic equation:
  61. magdyn += integral(wholedomain, 1/mu* curl(dof(a)) * curl(tf(a)) );
  62. magdyn += integral(conductor, sigma*dt(dof(a))*tf(a) + sigma* grad(dof(v))*tf(a) );
  63. // Electric equation:
  64. magdyn += integral(conductor, sigma*grad(dof(v))*grad(tf(v)) + sigma*dt(dof(a))*grad(tf(v)) );
  65. // Generate the algebraic matrices A and vector b of the Ax = b problem:
  66. magdyn.generate();
  67. // Get the x solution vector:
  68. vec sol = solve(magdyn.A(), magdyn.b());
  69. // Update the fields with the solution that has just been computed:
  70. a.setdata(wholedomain, sol);
  71. v.setdata(conductor, sol);
  72. // Write the magnetic induction field b = curl(a) [T], electric field e = -dt(a) - grad(v) [V/m] and current density j [A/m^2]:
  73. expression e = -dt(a) - grad(v);
  74. curl(a).write(wholedomain, "b.pos");
  75. e.write(conductor, "e.pos");
  76. (sigma*e).write(conductor, "j.pos");
  77. v.write(conductor, "v.pos");
  78. // Code validation line. Can be removed:
  79. double minj = norm(sigma*(-2*getpi()*50*a.harmonic(2) - grad(v.harmonic(3)))).min(tube,4)[0];
  80. std::cout << (minj < 216432 && minj > 216430);
  81. }
  82. int main(void)
  83. {
  84. SlepcInitialize(0,{},0,0);
  85. sparselizard();
  86. SlepcFinalize();
  87. return 0;
  88. }