main.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 (default is 1):
  45. a.setorder(wholedomain, 0);
  46. // Put a magnetic wall (i.e. set field a to 0) all around the domain (no magnetic flux can cross it):
  47. a.setconstraint(domainboundary);
  48. // Also ground v on face 'vout':
  49. v.setconstraint(vout);
  50. // Set v to 1V on face 'vin' for the in-phase component and to 0 for the quadrature component:
  51. v.harmonic(2).setconstraint(vin, 1);
  52. v.harmonic(3).setconstraint(vin);
  53. // Define the weak magnetodynamic formulation:
  54. formulation magdyn;
  55. // The strong form of the magnetodynamic a-v formulation is
  56. //
  57. // curl( 1/mu * curl(a) ) + sigma * (dt(a) + grad(v)) = js, with b = curl(a) and e = -dt(a) - grad(v)
  58. //
  59. // Magnetic equation:
  60. magdyn += integral(wholedomain, 1/mu* curl(dof(a)) * curl(tf(a)) );
  61. magdyn += integral(conductor, sigma*dt(dof(a))*tf(a) + sigma* grad(dof(v))*tf(a) );
  62. // Electric equation:
  63. magdyn += integral(conductor, sigma*grad(dof(v))*grad(tf(v)) + sigma*dt(dof(a))*grad(tf(v)) );
  64. // Generate the algebraic matrices A and vector b of the Ax = b problem:
  65. magdyn.generate();
  66. // Get the x solution vector:
  67. vec sol = solve(magdyn.A(), magdyn.b());
  68. // Update the fields with the solution that has just been computed:
  69. a.setdata(wholedomain, sol);
  70. v.setdata(conductor, sol);
  71. // 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]:
  72. expression e = -dt(a) - grad(v);
  73. curl(a).write(wholedomain, "b.pos");
  74. e.write(conductor, "e.pos");
  75. (sigma*e).write(conductor, "j.pos");
  76. v.write(conductor, "v.pos");
  77. // Code validation line. Can be removed:
  78. double minj = norm(sigma*(-2*getpi()*50*a.harmonic(2) - grad(v.harmonic(3)))).min(tube,4)[0];
  79. std::cout << (minj < 216432 && minj > 216430);
  80. }
  81. int main(void)
  82. {
  83. SlepcInitialize(0,{},0,0);
  84. sparselizard();
  85. SlepcFinalize();
  86. return 0;
  87. }