diff --git a/MagneticForces/InfiniteBox.geo b/MagneticForces/InfiniteBox.geo new file mode 100644 index 0000000000000000000000000000000000000000..0d9cb8523269bf9301be47852689a96739e39592 --- /dev/null +++ b/MagneticForces/InfiniteBox.geo @@ -0,0 +1,149 @@ +Function Cuboid +// This function receives a vector pnt[] with 8 points +// and generates 12 lines, 6 line loops, 1 volume, +// 1 physical volume and one physicale surface + +l12 = newl; Line(l12) = {pnt[0], pnt[1]}; +l23 = newl; Line(l23) = {pnt[1], pnt[2]}; +l34 = newl; Line(l34) = {pnt[2], pnt[3]}; +l41 = newl; Line(l41) = {pnt[3], pnt[0]}; +l56 = newl; Line(l56) = {pnt[4], pnt[5]}; +l67 = newl; Line(l67) = {pnt[5], pnt[6]}; +l78 = newl; Line(l78) = {pnt[6], pnt[7]}; +l85 = newl; Line(l85) = {pnt[7], pnt[4]}; +l15 = newl; Line(l15) = {pnt[0], pnt[4]}; +l26 = newl; Line(l26) = {pnt[1], pnt[5]}; +l37 = newl; Line(l37) = {pnt[2], pnt[6]}; +l48 = newl; Line(l48) = {pnt[3], pnt[7]}; + +ll1 = newll; Line Loop(ll1) = { l12, l23, l34, l41 }; +ll2 = newll; Line Loop(ll2) = { l56, l67, l78, l85 }; +ll3 = newll; Line Loop(ll3) = { l12, l26, -l56, -l15 }; +ll4 = newll; Line Loop(ll4) = { l23, l37, -l67, -l26 }; +ll5 = newll; Line Loop(ll5) = { l34, l48, -l78, -l37 }; +ll6 = newll; Line Loop(ll6) = { l41, l15, -l85, -l48 }; + +s1 = news; Plane Surface(s1) = { ll1 } ; +s2 = news; Plane Surface(s2) = { ll2 } ; +s3 = news; Plane Surface(s3) = { ll3 } ; +s4 = news; Plane Surface(s4) = { ll4 } ; +s5 = news; Plane Surface(s5) = { ll5 } ; +s6 = news; Plane Surface(s6) = { ll6 } ; + +sl = newsl; Surface Loop(sl) = { -s1, s2, s3, s4, s5, s6 }; +v = newv; Volume(v) = { sl }; + +If( Flag_TransfInf ) +//Mesh.Algorithm3D = 4; // (4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree) + For num In { l12:l85 } + Transfinite Line{ num } = 10; + EndFor + For num In { l15:l48 } + Transfinite Line{ num } = 5; + EndFor + For num In { s1:s6 } + Transfinite Surface{ num } ; + EndFor + Transfinite Volume{ v } ; +EndIf +Return + + +DefineConstant[ + Flag_InfiniteBox = {1, Choices{0,1}, Name "Infinite box/Add infinite box"} + Flag_TransfInf = {0, Choices{0,1}, Name "Infinite box/Transfinite mesh", Visible 0} + ratioInf = {1.5, Name "Infinite box/Ratio ext-int", Visible Flag_InfiniteBox} + //ratioLc = {25, Name "Infinite box/ration int-Lc", Visible Flag_InfiniteBox} + xInt = {1, Name "Infinite box/xInt", Visible 0} + yInt = {1, Name "Infinite box/yInt", Visible 0} + zInt = {1, Name "Infinite box/zInt", Visible 0} + xExt = {xInt*ratioInf, Name "Infinite box/xExt", Visible 0} + yExt = {yInt*ratioInf, Name "Infinite box/yExt", Visible 0} + zExt = {zInt*ratioInf, Name "Infinite box/zExt", Visible 0} + xCnt = {0, Name "Infinite box/xCenter", Visible 0} + yCnt = {0, Name "Infinite box/yCenter", Visible 0} + zCnt = {0, Name "Infinite box/zCenter", Visible 0} +]; + +If(!Flag_InfiniteBox) + Abort; // exit +EndIf + +// Compute parameters related to the Infinite box + +BoundingBox; +xCnt = (General.MinX + General.MaxX) / 2.; +yCnt = (General.MinY + General.MaxY) / 2.; +zCnt = (General.MinZ + General.MaxZ) / 2.; +xInt = (General.MaxX - General.MinX)/2. * ratioBox; +yInt = (General.MaxY - General.MinZ)/2. * ratioBox; +zInt = (General.MaxZ - General.MinZ)/2. * ratioBox; +xExt = xInt * ratioInf; +yExt = yInt * ratioInf; +zExt = zInt * ratioInf; +SetNumber("Infinite box/xInt",xInt); +SetNumber("Infinite box/yInt",yInt); +SetNumber("Infinite box/zInt",zInt); +SetNumber("Infinite box/xExt",xExt); +SetNumber("Infinite box/yExt",yExt); +SetNumber("Infinite box/zExt",zExt); +SetNumber("Infinite box/xCenter",xCnt); +SetNumber("Infinite box/yCenter",yCnt); +SetNumber("Infinite box/zCenter",zCnt); + +lc1inf = lc2; +lc2inf = lc1inf; + +p1 = newp; Point (p1) = {xCnt-xInt, yCnt-yInt, zCnt-zInt, lc1inf}; +p2 = newp; Point (p2) = {xCnt+xInt, yCnt-yInt, zCnt-zInt, lc1inf}; +p3 = newp; Point (p3) = {xCnt+xInt, yCnt+yInt, zCnt-zInt, lc1inf}; +p4 = newp; Point (p4) = {xCnt-xInt, yCnt+yInt, zCnt-zInt, lc1inf}; +p5 = newp; Point (p5) = {xCnt-xInt, yCnt-yInt, zCnt+zInt, lc1inf}; +p6 = newp; Point (p6) = {xCnt+xInt, yCnt-yInt, zCnt+zInt, lc1inf}; +p7 = newp; Point (p7) = {xCnt+xInt, yCnt+yInt, zCnt+zInt, lc1inf}; +p8 = newp; Point (p8) = {xCnt-xInt, yCnt+yInt, zCnt+zInt, lc1inf}; + +pp1 = newp; Point (pp1) = {xCnt-xExt, yCnt-yExt, zCnt-zExt, lc2inf}; +pp2 = newp; Point (pp2) = {xCnt+xExt, yCnt-yExt, zCnt-zExt, lc2inf}; +pp3 = newp; Point (pp3) = {xCnt+xExt, yCnt+yExt, zCnt-zExt, lc2inf}; +pp4 = newp; Point (pp4) = {xCnt-xExt, yCnt+yExt, zCnt-zExt, lc2inf}; +pp5 = newp; Point (pp5) = {xCnt-xExt, yCnt-yExt, zCnt+zExt, lc2inf}; +pp6 = newp; Point (pp6) = {xCnt+xExt, yCnt-yExt, zCnt+zExt, lc2inf}; +pp7 = newp; Point (pp7) = {xCnt+xExt, yCnt+yExt, zCnt+zExt, lc2inf}; +pp8 = newp; Point (pp8) = {xCnt-xExt, yCnt+yExt, zCnt+zExt, lc2inf}; + +SurfInf[] = {} ; +SurfExt[] = {} ; +VolInf[] = {}; + +pnt[]={p1,p2,p3,p4,pp1,pp2,pp3,pp4}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +pnt[]={p5,p6,p7,p8,pp5,pp6,pp7,pp8}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +pnt[]={p1,p2,p6,p5,pp1,pp2,pp6,pp5}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +pnt[]={p3,p4,p8,p7,pp3,pp4,pp8,pp7}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +pnt[]={p2,p3,p7,p6,pp2,pp3,pp7,pp6}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +pnt[]={p4,p1,p5,p8,pp4,pp1,pp5,pp8}; +Call Cuboid; +SurfInt[] += {s1} ; SurfExt[] += {s2} ; VolInf[] += {v}; + +Coherence; + +Physical Volume("InfiniteX", 1) = { VolInf[4], VolInf[5] }; +Physical Volume("InfiniteY", 2) = { VolInf[2], VolInf[3] }; +Physical Volume("InfiniteZ", 3) = { VolInf[0], VolInf[1] }; + + diff --git a/MagneticForces/magnets.geo b/MagneticForces/magnets.geo new file mode 100644 index 0000000000000000000000000000000000000000..89143ab0700d57d224c62d711b7d2cae74503a83 --- /dev/null +++ b/MagneticForces/magnets.geo @@ -0,0 +1,94 @@ +// include parameters common to geometry and solver + +Include "magnets_common.pro"; + +// define geometry-specific parameters +DefineConstant[ + lc1 = {TotalMemory <= 2048 ? 10*mm : 5*mm, Name "Parameters/2Mesh size on magnets [m]"} + lc2 = {TotalMemory <= 2048 ? 20*mm : 10*mm, Name "Parameters/2Mesh size at infinity [m]"} + ratioBox = {2.0, Name "Parameters/2Ratio Box to model size"} +]; + +// change global Gmsh options +Mesh.Optimize = 1; // optimize quality of tetrahedra +Mesh.VolumeEdges = 0; // hide volume edges +Geometry.ExactExtrusion = 0; // to allow rotation of extruded shapes +Solver.AutoMesh = 2; // always remesh if necessary (don't reuse mesh on disk) + +// create magnets +For i In {1:NumMagnets} + If(M~{i} == 0) // cylinder + p1 = newp; Point(p1) = {X~{i}, Y~{i}-L~{i}/2, Z~{i}, lc1}; + p2 = newp; Point(p2) = {X~{i}+R~{i}, Y~{i}-L~{i}/2, Z~{i}, lc1}; + p3 = newp; Point(p3) = {X~{i}, Y~{i}+L~{i}/2, Z~{i}, lc1}; + p4 = newp; Point(p4) = {X~{i}+R~{i}, Y~{i}+L~{i}/2, Z~{i}, lc1}; + l1 = newl; Line(l1) = {p1,p2}; l2 = newl; Line(l2) = {p2,p4}; + l3 = newl; Line(l3) = {p4,p3}; l4 = newl; Line(l4) = {p3,p1}; + ll1 = newll; Line Loop(ll1) = {l1,l2,l3,l4}; + s1 = news; Plane Surface(s1) = {ll1}; + e1[] = Extrude {{0, 1, 0}, {X~{i}, Y~{i}, Z~{i}}, Pi/2} { Surface{s1}; }; + e2[] = Extrude {{0, 1, 0}, {X~{i}, Y~{i}, Z~{i}}, Pi/2} { Surface{e1[0]}; }; + e3[] = Extrude {{0, 1, 0}, {X~{i}, Y~{i}, Z~{i}}, Pi/2} { Surface{e2[0]}; }; + e4[] = Extrude {{0, 1, 0}, {X~{i}, Y~{i}, Z~{i}}, Pi/2} { Surface{e3[0]}; }; + Magnet~{i}[] = {e1[1], e2[1], e3[1], e4[1]}; + EndIf + If(M~{i} == 1) // parallelepiped + p1 = newp; Point(p1) = {X~{i}-Lx~{i}/2, Y~{i}-Ly~{i}/2, Z~{i}-Lz~{i}/2, lc1}; + p2 = newp; Point(p2) = {X~{i}+Lx~{i}/2, Y~{i}-Ly~{i}/2, Z~{i}-Lz~{i}/2, lc1}; + p3 = newp; Point(p3) = {X~{i}+Lx~{i}/2, Y~{i}+Ly~{i}/2, Z~{i}-Lz~{i}/2, lc1}; + p4 = newp; Point(p4) = {X~{i}-Lx~{i}/2, Y~{i}+Ly~{i}/2, Z~{i}-Lz~{i}/2, lc1}; + l1 = newl; Line(l1) = {p1,p2}; l2 = newl; Line(l2) = {p2,p3}; + l3 = newl; Line(l3) = {p3,p4}; l4 = newl; Line(l4) = {p4,p1}; + ll1 = newll; Line Loop(ll1) = {l1,l2,l3,l4}; + s1 = news; Plane Surface(s1) = {ll1}; + e1[] = Extrude {0, 0, Lz~{i}} { Surface{s1}; }; + Magnet~{i}[] = {e1[1]}; + EndIf + Rotate { {0,0,1}, {X~{i},Y~{i},Z~{i}}, deg*Rz~{i} } { Volume{Magnet~{i}[]}; } + Rotate { {0,1,0}, {X~{i},Y~{i},Z~{i}}, deg*Ry~{i} } { Volume{Magnet~{i}[]}; } + Rotate { {1,0,0}, {X~{i},Y~{i},Z~{i}}, deg*Rx~{i} } { Volume{Magnet~{i}[]}; } + + Physical Volume(Sprintf("Magnet_%g",i),10*i) = Magnet~{i}[]; // magnet volume + skin~{i}[] = CombinedBoundary{ Volume{Magnet~{i}[]}; }; + Physical Surface(Sprintf("SkinMagnet_%g",i),10*i+1) = -skin~{i}[]; // magnet skin +EndFor + + +If (Flag_InfiniteBox ) + Include "InfiniteBox.geo"; +Else +// create air box around magnets + BoundingBox; // recompute model bounding box + cx = (General.MinX + General.MaxX) / 2; + cy = (General.MinY + General.MaxY) / 2; + cz = (General.MinZ + General.MaxZ) / 2; + lx = (General.MaxX - General.MinX) * 2 * ratioBox; + ly = (General.MaxY - General.MinZ) * ratioBox; + lz = (General.MaxZ - General.MinZ) * 2 * ratioBox; + p1 = newp; Point (p1) = {cx-lx/2, cy-ly/2, cz-lz/2, lc2}; + p2 = newp; Point (p2) = {cx+lx/2, cy-ly/2, cz-lz/2, lc2}; + l1 = newl; Line(l1) = {p1, p2}; + e1[] = Extrude {0, ly, 0} { Line{l1}; }; + e2[] = Extrude {0, 0, lz} { Surface{e1[1]}; }; + Delete { Volume{e2[1]}; } + SurfInt[] = { e1[1],e2[0],e2[2],e2[3],e2[4],e2[5] }; + SurfExt[] = SurfInt[]; +EndIf + + + +For num In {0:#SurfInt[]-1} + Printf("%g %g", num, SurfInt[num]); +EndFor + +temp = newsl; Surface Loop(temp) = { SurfInt[] }; +vv[] = { temp}; +For i In {1:NumMagnets} + temp = newsl; Surface Loop(temp) = { skin~{i}[] }; + vv[] += temp; +EndFor +v1 = newv; Volume(v1) = { vv[] }; +Physical Volume("AirBox", 4) = v1; + +Physical Surface("OuterSurface", 5) = { SurfExt[] }; +Physical Surface("InnerSurface", 6) = { SurfInt[] }; diff --git a/MagneticForces/magnets.pro b/MagneticForces/magnets.pro new file mode 100644 index 0000000000000000000000000000000000000000..3421498848cd9eb7e1c424d4b8056ba1c6ff251a --- /dev/null +++ b/MagneticForces/magnets.pro @@ -0,0 +1,380 @@ +/* ------------------------------------------------------------------- + Tutorial 9 : 3D magnetostatic dual formulations and magnetic forces + + Features: + - Dual 3D magnetostatic formulations + - Boundary condition at infinity with infinite elements + - Maxwell stress tensor and rigid-body magnetic forces + + To compute the solution in a terminal: + getdp magnets.pro + + To compute the solution interactively from the Gmsh GUI: + File > Open > magnets.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* + This rather didactic tutorial solves the electromagnetic field + and the rigid-body forces acting on a set of magnetic pieces + of parallelepipedic or cylindrical shape. + Besides position and dimension, each piece is attributed + a (constant) magnetic permability and/or a remanence field. + The pieces are all (a bit abusively) generically called "Magnet" + in the problem decription below, irresective of whether they are + truly permanent magnets or ferromagnetic barrels. + + The tutorial model proposes the both dual 3D magnetostatic formulations: + the magnetic vector potential formulation with spanning-tree gauging, + and the scalar magnetic potential formulation. + The later is rather simple in this case since, as there are no conductors, + the known coercive field hc[] is the only source field "hs" one needs + to represens the magnetic field: + + h = hs - grad phi , hs = -hc. + + As in tutorial 2 (magnetostatic field of an electromagnet), a shell + of so-called infinite elements is used here to impose the exact + zero-field boundary condition at infinity. + The shell is generated automatically by including "InfiniteBox.geo" + at the end of the geometrical description of the model. + It can be placed rather close of the magnets without loss of accuracy. + + The preferred way to compute electromagnetic forces in GetDP + is as an explicit by-product of the Maxwell stress tensor "TM[{b}]", + which is a material dependent function of the magnetic induction "b" field. + Exactly like we computed the heat flux "q(S)" through a surface "S" + using a special auxiliary function "g(S)" associated with that surface + in the tutorial "Tutorial 5 : thermal problem with contact resistances", + the magnetic force acting on a rigid body in empty space can be evaluated + as the flux of the Maxwell stress tensor through that surface. + There is one auxiliary function "g(SkinMagnet~{i}) = un~{i}" + for each magnet and the resultant magnetic force acting on "Magnet~{i}" + is given by the integral: + + f~{i} = Integral [ TM[{b}] * {-grad un~{i}} ] ; + + It should be insisted on the fact that the Maxwell stress is discontinuous + on material discontinuities, and that magnetic forces on rigid bodies + only depend on the Maxwell stress tensor of empty space and + on the "b" and "h" field distribution on the outer side of "SkinMagnet~{i}". + + "{-grad un~{i}}" in the above formula can be regarded + as the normal vector to "SkinMagnet~{i}" + in the one element thick layer "layer~{i}" of finite elements + around "Magnet~{i}", and "f~{i}", is thus indeed the flux of "TM[]" + through the surface of "Magnet~{i}". + + The support of "{-grad un~{i}}" is limited to "layer~{i}", + which is much smaller than "AirBox". + To speed up the computation of forces, a special domain "Vol_Force" + for force integrations is defined, which contains only + the layers "layer~{i}" of alla magnets. +*/ + +Include "magnets_common.pro" + +DefineConstant[ + // preset all getdp options and make them invisible + R_ = {"MagSta_a", Name "GetDP/1ResolutionChoices", Visible 1, + Choices {"MagSta_a", "MagSta_phi"}}, + C_ = {"-solve -v 5 -v2 -bin", Name "GetDP/9ComputeCommand", Visible 0} + P_ = {"", Name "GetDP/2PostOperationChoices", Visible 0} +]; + +Group{ + // Geometrical regions (give litteral labels to geometrical region numbers) + domInfX = Region[1]; + domInfY = Region[2]; + domInfZ = Region[3]; + AirBox = Region[4]; + Outer = Region[5]; + + For i In {1:NumMagnets} + Magnet~{i} = Region[ {(10*i)}]; + SkinMagnet~{i} = Region[ {(10*i+1)} ]; + Layer~{i} = Region[AirBox, OnOneSideOf SkinMagnet~{i}] ; + EndFor + + // Abstract Groups (group geometrical regions into formulation relevant groups) + Vol_Inf = Region[ {domInfX, domInfY, domInfZ} ]; + Vol_Air = Region[ {AirBox, Vol_Inf} ]; + + Vol_Magnet = Region[{}]; + Sur_Magnet = Region[{}]; + Vol_Force = Region[{}]; + For i In {1:NumMagnets} + Sur_Magnet += Region[SkinMagnet~{i}]; + Vol_Magnet += Region[Magnet~{i}]; + Vol_Layer += Region[Layer~{i}]; + EndFor + + Vol_mu = Region[ {Vol_Air, Vol_Magnet}]; + + Sur_Dirichlet_phi = Region[ Outer ]; + Sur_Dirichlet_a = Region[ Outer ]; + + Dom_Hgrad_phi = Region[ {Vol_Air, Vol_Magnet, Sur_Dirichlet_phi} ]; + Dom_Hcurl_a = Region[ {Vol_Air, Vol_Magnet, Sur_Dirichlet_a} ]; + Vol_Force = Region [ Vol_Layer ]; + //Vol_Force = Region [ Vol_Air ]; +} + +Function{ + mu0 = 4*Pi*1e-7; + mu[ Vol_Air ] = mu0; + + For i In {1:NumMagnets} + // coercive field of magnets + DefineConstant[ + HC~{i} = {-BR~{i}/mu0, + Name Sprintf("Parameters/Magnet %g/0Coercive magnetic field [Am^-1]", i), Visible 0} + ]; + hc[Magnet~{i}] = Rotate[Vector[0, HC~{i}, 0], Rx~{i}, Ry~{i}, Rz~{i}]; + br[Magnet~{i}] = Rotate[Vector[0, BR~{i}, 0], Rx~{i}, Ry~{i}, Rz~{i}]; + mu[Magnet~{i}] = mu0*MUR~{i}; + EndFor + + nu[] = 1.0/mu[]; + + // Maxwell stress tensor (valid for both formulations and linear materials + TM[] = ( SquDyadicProduct[$1] - SquNorm[$1] * TensorDiag[0.5, 0.5, 0.5] ) / mu[] ; +} + +Jacobian { + { Name Vol ; + Case { + { Region All ; Jacobian Vol ; } + {Region domInfX; Jacobian VolRectShell {xInt,xExt,1,xCnt,yCnt,zCnt};} + {Region domInfY; Jacobian VolRectShell {yInt,yExt,2,xCnt,yCnt,zCnt};} + {Region domInfZ; Jacobian VolRectShell {zInt,zExt,3,xCnt,yCnt,zCnt};} + } + } +} + +Integration { + { Name Int ; + Case { + { Type Gauss ; + Case { + { GeoElement Triangle ; NumberOfPoints 4 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } + { GeoElement Tetrahedron ; NumberOfPoints 4 ; } + { GeoElement Hexahedron ; NumberOfPoints 6 ; } + { GeoElement Prism ; NumberOfPoints 6 ; } + } + } + } + } +} + +Constraint { + { Name phi ; + Case { + { Region Sur_Dirichlet_phi ; Value 0. ; } + } + } + { Name a ; + Case { + { Region Sur_Dirichlet_a ; Value 0. ; } + } + } + { Name GaugeCondition_a ; Type Assign ; + Case { + { Region Dom_Hcurl_a ; SubRegion Sur_Dirichlet_a ; Value 0. ; } + } + } + For i In {1:NumMagnets} + { Name Magnet~{i} ; + Case { + { Region SkinMagnet~{i} ; Value 1. ; } + } + } + EndFor +} + +FunctionSpace { + { Name Hgrad_phi ; Type Form0 ; // scalar magnetic potential + BasisFunction { + { Name sn ; NameOfCoef phin ; Function BF_Node ; + Support Dom_Hgrad_phi ; Entity NodesOf[ All ] ; } + } + Constraint { + { NameOfCoef phin ; EntityType NodesOf ; NameOfConstraint phi ; } + } + } + { Name Hcurl_a; Type Form1; // vector magnetic potential + BasisFunction { + { Name se; NameOfCoef ae; Function BF_Edge; + Support Dom_Hcurl_a ;Entity EdgesOf[ All ]; } + } + Constraint { + { NameOfCoef ae; EntityType EdgesOf ; NameOfConstraint a; } + { NameOfCoef ae; EntityType EdgesOfTreeIn ; EntitySubType StartingOn ; + NameOfConstraint GaugeCondition_a ; } + } + } + // auxiliary field on layer of elements touching each magnet, for the + // accurate integration of the Maxwell stress tensor (using the gradient of + // this field) + For i In {1:NumMagnets} + { Name Magnet~{i} ; Type Form0 ; + BasisFunction { + { Name sn ; NameOfCoef un ; Function BF_GroupOfNodes ; + Support Vol_Air ; Entity GroupsOfNodesOf[ SkinMagnet~{i} ] ; } + } + Constraint { + { NameOfCoef un ; EntityType GroupsOfNodesOf ; NameOfConstraint Magnet~{i} ; } + } + } + EndFor +} + +Formulation { + { Name MagSta_phi ; Type FemEquation ; + Quantity { + { Name phi ; Type Local ; NameOfSpace Hgrad_phi ; } + For i In {1:NumMagnets} + { Name un~{i} ; Type Local ; NameOfSpace Magnet~{i} ; } + EndFor + } + Equation { + Galerkin { [ - mu[] * Dof{d phi} , {d phi} ] ; + In Vol_mu ; Jacobian Vol ; Integration Int ; } + Galerkin { [ - mu[] * hc[] , {d phi} ] ; + In Vol_Magnet ; Jacobian Vol ; Integration Int ; } + For i In {1:NumMagnets} // dummy term to define dofs for fully fixed space + Galerkin { [ 0 * Dof{un~{i}} , {un~{i}} ] ; + In Vol_Air ; Jacobian Vol ; Integration Int ; } + EndFor + } + } + { Name MagSta_a; Type FemEquation ; + Quantity { + { Name a ; Type Local ; NameOfSpace Hcurl_a ; } + For i In {1:NumMagnets} + { Name un~{i} ; Type Local ; NameOfSpace Magnet~{i} ; } + EndFor + } + Equation { + Galerkin { [ nu[] * Dof{d a} , {d a} ] ; + In Vol_mu ; Jacobian Vol ; Integration Int ; } + Galerkin { [ nu[] * br[] , {d a} ] ; + In Vol_Magnet ; Jacobian Vol ; Integration Int ; } + For i In {1:NumMagnets} + // dummy term to define dofs for fully fixed space + Galerkin { [ 0 * Dof{un~{i}} , {un~{i}} ] ; + In Vol_Air ; Jacobian Vol ; Integration Int ; } + EndFor + } + } +} + +Resolution { + { Name MagSta_phi ; + System { + { Name A ; NameOfFormulation MagSta_phi ; } + } + Operation { + Generate[A] ; Solve[A] ; SaveSolution[A] ; + PostOperation[MagSta_phi] ; + } + } + { Name MagSta_a ; + System { + { Name A ; NameOfFormulation MagSta_a ; } + } + Operation { + Generate[A] ; Solve[A] ; SaveSolution[A] ; + PostOperation[MagSta_a] ; + } + } +} + +PostProcessing { + { Name MagSta_phi ; NameOfFormulation MagSta_phi ; + Quantity { + { Name b ; + Value { Local { [ - mu[] * {d phi} ] ; In Dom_Hgrad_phi ; Jacobian Vol ; } + Local { [ - mu[] * hc[] ] ; In Vol_Magnet ; Jacobian Vol ; } } } + { Name h ; + Value { Local { [ - {d phi} ] ; In Dom_Hgrad_phi ; Jacobian Vol ; } } } + { Name hc ; Value { Local { [ hc[] ] ; In Vol_Magnet ; Jacobian Vol ; } } } + { Name phi ; Value { Local { [ {phi} ] ; In Dom_Hgrad_phi ; Jacobian Vol ; } } } + For i In {1:NumMagnets} + { Name un~{i} ; Value { Local { [ {un~{i}} ] ; In Vol_Force ; Jacobian Vol ; } } } + { Name f~{i} ; Value { Integral { [ - TM[-mu[] * {d phi}] * {d un~{i}} ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fx~{i} ; Value { Integral { [ CompX[- TM[-mu[] * {d phi}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fy~{i} ; Value { Integral { [ CompY[- TM[-mu[] * {d phi}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fz~{i} ; Value { Integral { [ CompZ[- TM[-mu[] * {d phi}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + EndFor + } + } + { Name MagSta_a ; NameOfFormulation MagSta_a ; + PostQuantity { + { Name b ; Value { Local { [ {d a} ]; In Dom_Hcurl_a ; Jacobian Vol; } } } + { Name a ; Value { Local { [ {a} ]; In Dom_Hcurl_a ; Jacobian Vol; } } } + { Name br ; Value { Local { [ br[] ]; In Vol_Magnet ; Jacobian Vol; } } } + For i In {1:NumMagnets} + { Name un~{i} ; Value { Local { [ {un~{i}} ] ; In Dom_Hcurl_a ; Jacobian Vol ; } } } + { Name f~{i} ; Value { Integral { [ - TM[{d a}] * {d un~{i}} ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fx~{i} ; Value { Integral { [ CompX[- TM[{d a}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fy~{i} ; Value { Integral { [ CompY[- TM[{d a}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + { Name fz~{i} ; Value { Integral { [ CompZ[- TM[{d a}] * {d un~{i}} ] ] ; + In Vol_Force ; Jacobian Vol ; Integration Int ; } } } + EndFor + } + } +} + +PostOperation { + { Name MagSta_phi ; NameOfPostProcessing MagSta_phi; + Operation { + Print[ b, OnElementsOf Vol_mu, File "b.pos" ] ; + Echo[ Str["l=PostProcessing.NbViews-1;", + "View[l].ArrowSizeMax = 100;", + "View[l].CenterGlyphs = 1;", + "View[l].VectorType = 1;" ] , + File "tmp.geo", LastTimeStepOnly] ; + For i In {1:NumMagnets} + Print[ f~{i}[Vol_Air], OnGlobal, Format Table, File > "F.dat" ]; + Print[ fx~{i}[Vol_Air], OnGlobal, Format Table, File > "Fx.dat", + SendToServer Sprintf("Output/Magnet %g/X force [N]", i), Color "Ivory" ]; + Print[ fy~{i}[Vol_Air], OnGlobal, Format Table, File > "Fy.dat", + SendToServer Sprintf("Output/Magnet %g/Y force [N]", i), Color "Ivory" ]; + Print[ fz~{i}[Vol_Air], OnGlobal, Format Table, File > "Fz.dat", + SendToServer Sprintf("Output/Magnet %g/Z force [N]", i), Color "Ivory" ]; + EndFor + } + } + { Name MagSta_a ; NameOfPostProcessing MagSta_a ; + Operation { + Print[ b, OnElementsOf Vol_mu, File "b.pos" ]; + Echo[ Str["l=PostProcessing.NbViews-1;", + "View[l].ArrowSizeMax = 100;", + "View[l].CenterGlyphs = 1;", + "View[l].VectorType = 1;" ] , + File "tmp.geo", LastTimeStepOnly] ; + //Print[ br, OnElementsOf Vol_Magnet, File "br.pos" ]; + //Print[ a, OnElementsOf Vol_mu, File "a.pos" ]; + For i In {1:NumMagnets} + //Print[ un~{i}, OnElementsOf Domain, File "un.pos" ]; + Print[ f~{i}[Vol_Air], OnGlobal, Format Table, File > "F.dat" ]; + Print[ fx~{i}[Vol_Air], OnGlobal, Format Table, File > "Fx.dat", + SendToServer Sprintf("Output/Magnet %g/X force [N]", i), Color "Ivory" ]; + Print[ fy~{i}[Vol_Air], OnGlobal, Format Table, File > "Fy.dat", + SendToServer Sprintf("Output/Magnet %g/Y force [N]", i), Color "Ivory" ]; + Print[ fz~{i}[Vol_Air], OnGlobal, Format Table, File > "Fz.dat", + SendToServer Sprintf("Output/Magnet %g/Z force [N]", i), Color "Ivory" ]; + EndFor + } + } +} + diff --git a/MagneticForces/magnets_common.pro b/MagneticForces/magnets_common.pro new file mode 100644 index 0000000000000000000000000000000000000000..3c75dce75aa16ece8ea75c1329382fc82947e957 --- /dev/null +++ b/MagneticForces/magnets_common.pro @@ -0,0 +1,65 @@ +mm = 1.e-3; +deg = Pi/180.; +DefineConstant[ + NumMagnets = {2, Min 1, Max 20, Step 1, Name "Parameters/0Number of magnets"} + Flag_InfiniteBox = {1, Choices{0,1}, Name "Infinite box/Add infinite box"} + Flag_FullMenu = {0, Choices{0,1}, Name "Parameters/Show all parameters"} + //DistToBox = {50*mm, Name "Infinite box/Distance to box [m]", Visible Flag_InfiniteBox} + //lcInf = {DistToBox, Name "Infinite box/Mesh size", Visible Flag_InfiniteBox} +]; + +For i In {1:NumMagnets} + DefineConstant[ + X~{i} = {0, Min -100*mm, Max 100*mm, Step mm, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/0X position [m]", i) }, + Y~{i} = { (i-1)*60*mm, Min -100*mm, Max 100*mm, Step mm, + Name Sprintf("Parameters/Magnet %g/0Y position [m]", i) }, + Z~{i} = {0, Min -100*mm, Max 100*mm, Step mm, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/0Z position [m]", i) }, + + M~{i} = {(i==1)?0:1, Choices{0="Cylinder",1="Cube"}, + Name Sprintf("Parameters/Magnet %g/00Shape", i)}, + + R~{i} = {20*mm, Min mm, Max 100*mm, Step mm, + Name Sprintf("Parameters/Magnet %g/1Radius [m]", i), + Visible (M~{i} == 0) }, + L~{i} = {50*mm, Min mm, Max 100*mm, Step mm, + Name Sprintf("Parameters/Magnet %g/1Length [m]", i), + Visible (M~{i} == 0) }, + + Lx~{i} = {50*mm, Min mm, Max 100*mm, Step mm, + Name Sprintf("Parameters/Magnet %g/1X length [m]", i), + Visible (M~{i} == 1) }, + Ly~{i} = {50*mm, Min mm, Max 100*mm, Step mm, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/1XY aspect ratio", i), + Visible (M~{i} == 1) }, + Lz~{i} = {50*mm, Min mm, Max 100*mm, Step mm, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/1XZ aspect ration", i), + Visible (M~{i} == 1) }, + + Rx~{i} = {0, Min -Pi, Max Pi, Step Pi/180, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/2X rotation [deg]", i) }, + Ry~{i} = {0, Min -Pi, Max Pi, Step Pi/180, Visible Flag_FullMenu, + Name Sprintf("Parameters/Magnet %g/2Y rotation [deg]", i) }, + Rz~{i} = {0, Min -Pi, Max Pi, Step Pi/180, + Name Sprintf("Parameters/Magnet %g/2Z rotation [deg]", i) }, + + MUR~{i} = {(i==1)?1.:1000., + Name Sprintf("Parameters/Magnet %g/3Mu relative []", i)}, + BR~{i} = {(i==1)?1.0:0.0, + Name Sprintf("Parameters/Magnet %g/3Br [T]", i)} + ]; +EndFor + +//The geometrical parameters of the Infinite box. +DefineConstant[ + xInt = {1, Name "Infinite box/xInt", Visible 0} + yInt = {1, Name "Infinite box/yInt", Visible 0} + zInt = {1, Name "Infinite box/zInt", Visible 0} + xExt = {xInt*2, Name "Infinite box/xExt", Visible 0} + yExt = {yInt*2, Name "Infinite box/yExt", Visible 0} + zExt = {zInt*2, Name "Infinite box/zExt", Visible 0} + xCnt = {0, Name "Infinite box/xCenter", Visible 0} + yCnt = {0, Name "Infinite box/yCenter", Visible 0} + zCnt = {0, Name "Infinite box/zCenter", Visible 0} +];