From 38856f1dbb5af215b19e3982fc13e570768369d4 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Fri, 16 Mar 2018 12:05:47 +0100 Subject: [PATCH] train again to unformize line endings --- CircuitCoupling/RLC_circuit.geo | 66 +- CircuitCoupling/RLC_circuit.pro | 730 +++++++-------- CircuitCoupling/RLC_circuit_common.pro | 24 +- CircuitCoupling/R_circuit.geo | 78 +- CircuitCoupling/R_circuit.pro | 684 +++++++------- CircuitCoupling/R_circuit_common.pro | 30 +- Elasticity/wrench2D.geo | 144 +-- Elasticity/wrench2D.pro | 700 +++++++------- Elasticity/wrench2D_common.pro | 58 +- Electrostatics/microstrip.geo | 116 +-- ElectrostaticsFloating/floating.geo | 110 +-- ElectrostaticsFloating/floating.pro | 694 +++++++------- Magnetodynamics/Lib_MagStaDyn_av_2D_Cir.pro | 956 ++++++++++---------- Magnetodynamics/electromagnet.geo | 108 +-- Magnetodynamics/electromagnet.pro | 178 ++-- Magnetodynamics/electromagnet_common.pro | 8 +- Magnetodynamics/transfo.geo | 346 +++---- Magnetodynamics/transfo.pro | 518 +++++------ Magnetodynamics/transfo_common.pro | 98 +- Magnetostatics/electromagnet.geo | 108 +-- Magnetostatics/electromagnet.pro | 610 ++++++------- Magnetostatics/electromagnet_common.pro | 8 +- PotentialFlow/magnus.geo | 142 +-- PotentialFlow/magnus.pro | 862 +++++++++--------- PotentialFlow/magnus_common.pro | 54 +- PotentialFlow/nacaAirfoil.geo | 444 ++++----- Thermics/brick.geo | 222 ++--- Thermics/brick.pro | 840 ++++++++--------- Thermics/brick_common.pro | 74 +- 29 files changed, 4505 insertions(+), 4505 deletions(-) diff --git a/CircuitCoupling/RLC_circuit.geo b/CircuitCoupling/RLC_circuit.geo index cd10b79..2bb9299 100644 --- a/CircuitCoupling/RLC_circuit.geo +++ b/CircuitCoupling/RLC_circuit.geo @@ -1,33 +1,33 @@ -// Just 3 cubes - -Include "RLC_circuit_common.pro"; - -lc = 0.25; // Characteristic length - -Point(1) = {0, 0, 0, lc}; -Extrude {1, 0, 0} { - Point{1}; -} -Extrude {0, 1, 0} { - Line{1}; -} -Extrude {0, 0, 1} { - Surface{5}; -} -Translate {2, 0, 0} { - Duplicata { Volume{1}; } -} -Translate {4, 0, 0} { - Duplicata { Volume{1}; } -} - -Physical Surface(Cube1Top) = {27}; -Physical Surface(Cube1Bottom) = {5}; -Physical Surface(Cube2Top) = {34}; -Physical Surface(Cube2Bottom) = {29}; -Physical Surface(Cube3Top) = {61}; -Physical Surface(Cube3Bottom) = {56}; - -Physical Volume(Cube1) = {1}; -Physical Volume(Cube2) = {28}; -Physical Volume(Cube3) = {55}; +// Just 3 cubes + +Include "RLC_circuit_common.pro"; + +lc = 0.25; // Characteristic length + +Point(1) = {0, 0, 0, lc}; +Extrude {1, 0, 0} { + Point{1}; +} +Extrude {0, 1, 0} { + Line{1}; +} +Extrude {0, 0, 1} { + Surface{5}; +} +Translate {2, 0, 0} { + Duplicata { Volume{1}; } +} +Translate {4, 0, 0} { + Duplicata { Volume{1}; } +} + +Physical Surface(Cube1Top) = {27}; +Physical Surface(Cube1Bottom) = {5}; +Physical Surface(Cube2Top) = {34}; +Physical Surface(Cube2Bottom) = {29}; +Physical Surface(Cube3Top) = {61}; +Physical Surface(Cube3Bottom) = {56}; + +Physical Volume(Cube1) = {1}; +Physical Volume(Cube2) = {28}; +Physical Volume(Cube3) = {55}; diff --git a/CircuitCoupling/RLC_circuit.pro b/CircuitCoupling/RLC_circuit.pro index e668260..9c94f67 100644 --- a/CircuitCoupling/RLC_circuit.pro +++ b/CircuitCoupling/RLC_circuit.pro @@ -1,365 +1,365 @@ -/* ------------------------------------------------------------------- - Tutorial 8b : circuit coupling - RLC circuit - - Features: - - Electrokinetic formulation coupled with RLC circuit - - Transient resolution - - To compute the solution in a terminal: - getdp RLC_circuit -solve dynamic -pos Cube_Top_Values_ASCII - - To compute the solution interactively from the Gmsh GUI: - File > Open > RLC_circuit.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* - This example shows how to implement a circuit with discrete resistors, - capacitors, inductors, voltage- and current-sources in a transient finite - element simulation. There are three separate cubes, each with a certain - conductivity. The bottom of all cubes is kept at 0V via the constraint - Voltage_3D. The cubes are connected according the `RLC_circuit.jpg` schematic. -*/ - -Include "RLC_circuit_common.pro"; - -// FEM domain group data -Group { - // Surfaces - Top1 = Region[Cube1Top]; - Bottom1 = Region[Cube1Bottom]; - Top2 = Region[Cube2Top]; - Bottom2 = Region[Cube2Bottom]; - Top3 = Region[Cube3Top]; - Bottom3 = Region[Cube3Bottom]; - - // Volumes - Cube1 = Region[Cube1]; - Cube2 = Region[Cube2]; - Cube3 = Region[Cube3]; - - // FEM Electrical regions - // * all volumes - Vol_Ele = Region[{Cube1, Cube2, Cube3}]; - // * all surfaces connected to the lumped element circuit - Sur_Ele = Region[{Top1, Bottom1, Top2, Bottom2, Top3, Bottom3}]; - // * total electrical computation domain - Dom_Ele = Region[{Vol_Ele, Sur_Ele}]; -} - -// Circuit group data - Fictive regions for the circuit elements -Group { - - // Sources - CurrentSource1 = Region[{3001}]; - VoltageSource1 = Region[{3002}]; - - // Resistors - R1 = Region[{4001}]; - R2 = Region[{4002}]; - - // Inductors - L1 = Region[{4003}]; - - // Capacitors - C1 = Region[{4004}]; - - Resistance_Cir = Region[{R1, R2}]; // All resistors - Inductance_Cir = Region[{L1}]; // All inductors - Capacitance_Cir = Region[{C1}]; // All capacitors - SourceI_Cir = Region[{CurrentSource1}]; // All current sources - SourceV_Cir = Region[{VoltageSource1}]; // All voltage sources - - // Complete circuit domain containing all circuit elements - Domain_Cir = Region[{Resistance_Cir, Inductance_Cir, Capacitance_Cir, - SourceI_Cir, SourceV_Cir}]; -} - -Function { - // Simulation parameters - tStop = 10.0e-6; // Stop time [s] - tStep = 100e-9; // Time step [s] - nStrobe= 1; // Strobe periode for saving the result - - SaveFct[] = !($TimeStep % nStrobe); // Only each nStrobe-th time-step is saved - - // FEM domain function data - // ------------------------ - - Vbottom = 0.0; // Absolute voltage at the bottom of all cubes - - // Geometry of a cube - w = 1.0; // Width [m] - l = 1.0; // Length [m] - h = 1.0; // Height [m] - - // Resistance - Rcube1 = 10.0; // Resistance of cube 1 [Ohm] - Rcube2 = 40.0; // Resistance of cube 2 [Ohm] - Rcube3 = 20.0; // Resistance of cube 3 [Ohm] - - // Specific electrical conductivity [S*m/m^2] - kappa[Cube1] = h / (w * l * Rcube1); - kappa[Cube2] = h / (w * l * Rcube2); - kappa[Cube3] = h / (w * l * Rcube3); - - // Circuit domain function data - // ---------------------------- - - // Resistors - R[R1] = 30.0; // Resistance of R1 [Ohm] - R[R2] = 40.0; // Resistance of R2 [Ohm] - - // Inductors - L[L1] = 100.0e-6; // Inductance of L1 [H] - - // Capacitors - C[C1] = 250.0e-9; // Capacitance of C1 [F] - - // Note: All voltages and currents are assigned / initialized in the - // Constraint-block -} - -// FEM domain constraint data -Constraint { - { Name Current_3D ; Type Assign ; - Case { - } - } - { Name Voltage_3D ; Type Assign ; - Case { - { Region Bottom1; Type Assign; Value Vbottom; } - { Region Bottom2; Type Assign; Value Vbottom; } - { Region Bottom3; Type Assign; Value Vbottom; } - } - } -} - -// Circuit domain constraint data -Constraint { - { Name Current_Cir ; - Case { - { Region CurrentSource1; Type Assign; Value 1.0; } // CurrentSource1 has 1.0 A - { Region L1; Type Init; Value 1.0; } // Initial current of L1 is 1.0 A - } - } - { Name Voltage_Cir ; - Case { - { Region VoltageSource1; Type Assign; Value 80.0; } // VoltageSource1 has 80.0 V - { Region C1; Type Init; Value 0.0; } // Initial voltage of C1 = 0.0 V - } - } - - { Name ElectricalCircuit ; Type Network ; - Case Circuit1 { - // Circuit for cube 1: - { Region VoltageSource1; Branch{ 1, 10};} - { Region R1; Branch{ 1, 2};} - // The voltage between nodes 2 and 3 corresponds to the absolute voltage - // of the surface Top1: - { Region Top1; Branch{ 2, 3};} - // Note the reverse order of the nodes in the next branch: it's for - // subtracting the bottom voltage. - { Region Bottom1; Branch{ 10, 3};} - // With the two lines above, the voltage between node 2 and 10 corresponds - // to the voltage drop over the cube regardless what the absolute voltages - // are. The current between node 2 and 3 corresponds to the absolute - // current flowing through Top1. The same is valid for Bottom1. Due to the - // reverse order here the current has the opposite sign. This is correct - // because the current flowing IN Top1 is flowing OUT of Bottom1. Note - // that in this particular circuit it is actually not necessary to include - // the bottom faces in the netlist, because all bottoms are kept at 0 V - // via constraint Voltage_3D... But then all Bottom faces have to be - // excluded also in the region Sur_Ele! - - // Circuit for cube 2: - { Region L1; Branch{ 4, 10};} - { Region R2; Branch{ 4, 10};} - { Region Top2; Branch{ 4, 5};} - { Region Bottom2; Branch{10, 5};} - - // Circuit for cube 3 - { Region CurrentSource1; Branch{ 6, 10};} - { Region C1; Branch{ 6, 10};} - { Region Top3; Branch{ 6, 7};} - { Region Bottom3; Branch{10, 7};} - } - } -} - -Jacobian { - { Name JVol ; - Case { - { Region Region[{Vol_Ele}]; Jacobian Vol; } - { Region Region[{Sur_Ele}]; Jacobian Sur; } - } - } -} - -Integration { - { Name I1 ; - Case { - { Type Gauss ; - Case { - { GeoElement Point ; NumberOfPoints 1 ; } - { GeoElement Line ; NumberOfPoints 5 ; } - { GeoElement Triangle ; NumberOfPoints 6 ; } - { GeoElement Quadrangle ; NumberOfPoints 7 ; } - { GeoElement Tetrahedron ; NumberOfPoints 15 ; } - { GeoElement Hexahedron ; NumberOfPoints 34 ; } - { GeoElement Prism ; NumberOfPoints 21 ; } - } - } - } - } -} - -FunctionSpace { - // Function space for the FEM domain - { Name Hgrad_V; Type Form0; - BasisFunction { - // All nodes but the grouped nodes of the surfaces for connecting the - // circuitry - { Name sn; NameOfCoef vn; Function BF_Node; - Support Dom_Ele; Entity NodesOf[ All, Not Sur_Ele ]; } - // Grouped nodes: Each surface of Sur_Ele has just one single voltage - { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; - Support Dom_Ele; Entity GroupsOfNodesOf[ Sur_Ele ]; } - } - GlobalQuantity { - { Name U; Type AliasOf; NameOfCoef vf; } - { Name I; Type AssociatedWith; NameOfCoef vf; } - } - Constraint { - { NameOfCoef vn; EntityType NodesOf ; NameOfConstraint Voltage_3D; } - { NameOfCoef U; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage_3D; } - { NameOfCoef I; EntityType GroupsOfNodesOf ; NameOfConstraint Current_3D; } - } - } - - // Function space for the circuit domain - { Name Hregion_Cir; Type Scalar; - BasisFunction { - { Name sn; NameOfCoef ir; Function BF_Region; - Support Domain_Cir; Entity Domain_Cir; } - } - GlobalQuantity { - { Name Iz; Type AliasOf; NameOfCoef ir; } - { Name Uz; Type AssociatedWith; NameOfCoef ir; } - } - Constraint { - { NameOfCoef Uz ; EntityType Region ; NameOfConstraint Voltage_Cir ; } - { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; } - } - } - -} - - -Formulation { - { Name dynamic; Type FemEquation; - Quantity { - { Name V; Type Local; NameOfSpace Hgrad_V; } - { Name U; Type Global; NameOfSpace Hgrad_V [U]; } - { Name I; Type Global; NameOfSpace Hgrad_V [I]; } - { Name Uz; Type Global; NameOfSpace Hregion_Cir [Uz]; } - { Name Iz; Type Global; NameOfSpace Hregion_Cir [Iz]; } - } - Equation { - // FEM domain - Integral { [ kappa[] * Dof{d V}, {d V} ]; In Vol_Ele; - Integration I1; Jacobian JVol; } - GlobalTerm{ [ Dof{I}, {U} ]; In Sur_Ele; } - - // Circuit related terms - // Resistance equation - GlobalTerm{ [ Dof{Uz}, {Iz} ]; In Resistance_Cir; } - GlobalTerm{ [ R[] * Dof{Iz}, {Iz} ]; In Resistance_Cir; } - - // Inductance equation - GlobalTerm{ [ Dof{Uz}, {Iz} ]; In Inductance_Cir; } - GlobalTerm{ DtDof[ L[] * Dof{Iz}, {Iz} ]; In Inductance_Cir; } - - // Capacitance equation - GlobalTerm{ [ Dof{Iz}, {Iz} ]; In Capacitance_Cir; } - GlobalTerm{ DtDof[ C[] * Dof{Uz}, {Iz} ]; In Capacitance_Cir; } - - // Inserting the network - GlobalEquation { Type Network; NameOfConstraint ElectricalCircuit; - { Node {I}; Loop {U}; Equation {I}; In Sur_Ele; } - { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } - } - } - } -} - -Resolution { - { Name dynamic; - System { - { Name A; NameOfFormulation dynamic; } - } - Operation { - InitSolution[A]; - TimeLoopTheta[0.0, tStop, tStep, 1.0]{ - Generate[A]; - Solve[A]; - Test[SaveFct[]] { SaveSolution[A]; } - } - } - } -} - -PostProcessing { - { Name Ele; NameOfFormulation dynamic; - Quantity { - { Name V; Value{ Local{ [ {V} ]; In Vol_Ele; Jacobian JVol;} } } - { Name Jv; Value{ Local{ [ -kappa[]*{d V} ]; In Vol_Ele; Jacobian JVol;} } } - { Name J; Value{ Local{ [ Norm[kappa[]*{d V}] ]; In Vol_Ele; Jacobian JVol;} } } - { Name U; Value { Term { [ {U} ]; In Sur_Ele; } } } - // The minus sign here is for getting positive currents at the top of the - // cubes. This is because incomming currents are negative. - { Name I; Value { Term { [ -{I} ]; In Sur_Ele; } } } - } - } -} - -PostOperation { - // Absolute voltage everywhere [V] - { Name V; NameOfPostProcessing Ele; - Operation { - Print[ V, OnElementsOf Vol_Ele, TimeLegend, File "Result_V.pos"]; - } - } - // Current through the top surfaces of the cubes [A] - { Name I_Top; NameOfPostProcessing Ele; - Operation { - Print[ I, OnElementsOf Region[{Top1, Top2, Top3}], TimeLegend, - File "Result_I_Top.pos"]; - } - } - // Current density vectors everywhere [A/m^2] - { Name J_vectors; NameOfPostProcessing Ele; - Operation { - Print[ Jv, OnElementsOf Vol_Ele, TimeLegend, File "Result_J_vectors.pos"]; - } - } - // Magnitude of current density everywhere [A/m^2] - { Name J_magnitude; NameOfPostProcessing Ele; - Operation { - Print[ J, OnElementsOf Vol_Ele, TimeLegend, File "Result_J.pos"]; - } - } - // Store the results in an ASCII file - { Name Cube_Top_Values_ASCII; NameOfPostProcessing Ele; - Operation { - Print[U, OnRegion Top1, File "Result_Cube1TopValues.txt", Format TimeTable]; - Print[U, OnRegion Top2, File "Result_Cube2TopValues.txt", Format TimeTable]; - Print[U, OnRegion Top3, File "Result_Cube3TopValues.txt", Format TimeTable]; - - Print[I, OnRegion Top1, File > "Result_Cube1TopValues.txt", Format TimeTable]; - Print[I, OnRegion Top2, File > "Result_Cube2TopValues.txt", Format TimeTable]; - Print[I, OnRegion Top3, File > "Result_Cube3TopValues.txt", Format TimeTable]; - } - } - -} +/* ------------------------------------------------------------------- + Tutorial 8b : circuit coupling - RLC circuit + + Features: + - Electrokinetic formulation coupled with RLC circuit + - Transient resolution + + To compute the solution in a terminal: + getdp RLC_circuit -solve dynamic -pos Cube_Top_Values_ASCII + + To compute the solution interactively from the Gmsh GUI: + File > Open > RLC_circuit.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* + This example shows how to implement a circuit with discrete resistors, + capacitors, inductors, voltage- and current-sources in a transient finite + element simulation. There are three separate cubes, each with a certain + conductivity. The bottom of all cubes is kept at 0V via the constraint + Voltage_3D. The cubes are connected according the `RLC_circuit.jpg` schematic. +*/ + +Include "RLC_circuit_common.pro"; + +// FEM domain group data +Group { + // Surfaces + Top1 = Region[Cube1Top]; + Bottom1 = Region[Cube1Bottom]; + Top2 = Region[Cube2Top]; + Bottom2 = Region[Cube2Bottom]; + Top3 = Region[Cube3Top]; + Bottom3 = Region[Cube3Bottom]; + + // Volumes + Cube1 = Region[Cube1]; + Cube2 = Region[Cube2]; + Cube3 = Region[Cube3]; + + // FEM Electrical regions + // * all volumes + Vol_Ele = Region[{Cube1, Cube2, Cube3}]; + // * all surfaces connected to the lumped element circuit + Sur_Ele = Region[{Top1, Bottom1, Top2, Bottom2, Top3, Bottom3}]; + // * total electrical computation domain + Dom_Ele = Region[{Vol_Ele, Sur_Ele}]; +} + +// Circuit group data - Fictive regions for the circuit elements +Group { + + // Sources + CurrentSource1 = Region[{3001}]; + VoltageSource1 = Region[{3002}]; + + // Resistors + R1 = Region[{4001}]; + R2 = Region[{4002}]; + + // Inductors + L1 = Region[{4003}]; + + // Capacitors + C1 = Region[{4004}]; + + Resistance_Cir = Region[{R1, R2}]; // All resistors + Inductance_Cir = Region[{L1}]; // All inductors + Capacitance_Cir = Region[{C1}]; // All capacitors + SourceI_Cir = Region[{CurrentSource1}]; // All current sources + SourceV_Cir = Region[{VoltageSource1}]; // All voltage sources + + // Complete circuit domain containing all circuit elements + Domain_Cir = Region[{Resistance_Cir, Inductance_Cir, Capacitance_Cir, + SourceI_Cir, SourceV_Cir}]; +} + +Function { + // Simulation parameters + tStop = 10.0e-6; // Stop time [s] + tStep = 100e-9; // Time step [s] + nStrobe= 1; // Strobe periode for saving the result + + SaveFct[] = !($TimeStep % nStrobe); // Only each nStrobe-th time-step is saved + + // FEM domain function data + // ------------------------ + + Vbottom = 0.0; // Absolute voltage at the bottom of all cubes + + // Geometry of a cube + w = 1.0; // Width [m] + l = 1.0; // Length [m] + h = 1.0; // Height [m] + + // Resistance + Rcube1 = 10.0; // Resistance of cube 1 [Ohm] + Rcube2 = 40.0; // Resistance of cube 2 [Ohm] + Rcube3 = 20.0; // Resistance of cube 3 [Ohm] + + // Specific electrical conductivity [S*m/m^2] + kappa[Cube1] = h / (w * l * Rcube1); + kappa[Cube2] = h / (w * l * Rcube2); + kappa[Cube3] = h / (w * l * Rcube3); + + // Circuit domain function data + // ---------------------------- + + // Resistors + R[R1] = 30.0; // Resistance of R1 [Ohm] + R[R2] = 40.0; // Resistance of R2 [Ohm] + + // Inductors + L[L1] = 100.0e-6; // Inductance of L1 [H] + + // Capacitors + C[C1] = 250.0e-9; // Capacitance of C1 [F] + + // Note: All voltages and currents are assigned / initialized in the + // Constraint-block +} + +// FEM domain constraint data +Constraint { + { Name Current_3D ; Type Assign ; + Case { + } + } + { Name Voltage_3D ; Type Assign ; + Case { + { Region Bottom1; Type Assign; Value Vbottom; } + { Region Bottom2; Type Assign; Value Vbottom; } + { Region Bottom3; Type Assign; Value Vbottom; } + } + } +} + +// Circuit domain constraint data +Constraint { + { Name Current_Cir ; + Case { + { Region CurrentSource1; Type Assign; Value 1.0; } // CurrentSource1 has 1.0 A + { Region L1; Type Init; Value 1.0; } // Initial current of L1 is 1.0 A + } + } + { Name Voltage_Cir ; + Case { + { Region VoltageSource1; Type Assign; Value 80.0; } // VoltageSource1 has 80.0 V + { Region C1; Type Init; Value 0.0; } // Initial voltage of C1 = 0.0 V + } + } + + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + // Circuit for cube 1: + { Region VoltageSource1; Branch{ 1, 10};} + { Region R1; Branch{ 1, 2};} + // The voltage between nodes 2 and 3 corresponds to the absolute voltage + // of the surface Top1: + { Region Top1; Branch{ 2, 3};} + // Note the reverse order of the nodes in the next branch: it's for + // subtracting the bottom voltage. + { Region Bottom1; Branch{ 10, 3};} + // With the two lines above, the voltage between node 2 and 10 corresponds + // to the voltage drop over the cube regardless what the absolute voltages + // are. The current between node 2 and 3 corresponds to the absolute + // current flowing through Top1. The same is valid for Bottom1. Due to the + // reverse order here the current has the opposite sign. This is correct + // because the current flowing IN Top1 is flowing OUT of Bottom1. Note + // that in this particular circuit it is actually not necessary to include + // the bottom faces in the netlist, because all bottoms are kept at 0 V + // via constraint Voltage_3D... But then all Bottom faces have to be + // excluded also in the region Sur_Ele! + + // Circuit for cube 2: + { Region L1; Branch{ 4, 10};} + { Region R2; Branch{ 4, 10};} + { Region Top2; Branch{ 4, 5};} + { Region Bottom2; Branch{10, 5};} + + // Circuit for cube 3 + { Region CurrentSource1; Branch{ 6, 10};} + { Region C1; Branch{ 6, 10};} + { Region Top3; Branch{ 6, 7};} + { Region Bottom3; Branch{10, 7};} + } + } +} + +Jacobian { + { Name JVol ; + Case { + { Region Region[{Vol_Ele}]; Jacobian Vol; } + { Region Region[{Sur_Ele}]; Jacobian Sur; } + } + } +} + +Integration { + { Name I1 ; + Case { + { Type Gauss ; + Case { + { GeoElement Point ; NumberOfPoints 1 ; } + { GeoElement Line ; NumberOfPoints 5 ; } + { GeoElement Triangle ; NumberOfPoints 6 ; } + { GeoElement Quadrangle ; NumberOfPoints 7 ; } + { GeoElement Tetrahedron ; NumberOfPoints 15 ; } + { GeoElement Hexahedron ; NumberOfPoints 34 ; } + { GeoElement Prism ; NumberOfPoints 21 ; } + } + } + } + } +} + +FunctionSpace { + // Function space for the FEM domain + { Name Hgrad_V; Type Form0; + BasisFunction { + // All nodes but the grouped nodes of the surfaces for connecting the + // circuitry + { Name sn; NameOfCoef vn; Function BF_Node; + Support Dom_Ele; Entity NodesOf[ All, Not Sur_Ele ]; } + // Grouped nodes: Each surface of Sur_Ele has just one single voltage + { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; + Support Dom_Ele; Entity GroupsOfNodesOf[ Sur_Ele ]; } + } + GlobalQuantity { + { Name U; Type AliasOf; NameOfCoef vf; } + { Name I; Type AssociatedWith; NameOfCoef vf; } + } + Constraint { + { NameOfCoef vn; EntityType NodesOf ; NameOfConstraint Voltage_3D; } + { NameOfCoef U; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage_3D; } + { NameOfCoef I; EntityType GroupsOfNodesOf ; NameOfConstraint Current_3D; } + } + } + + // Function space for the circuit domain + { Name Hregion_Cir; Type Scalar; + BasisFunction { + { Name sn; NameOfCoef ir; Function BF_Region; + Support Domain_Cir; Entity Domain_Cir; } + } + GlobalQuantity { + { Name Iz; Type AliasOf; NameOfCoef ir; } + { Name Uz; Type AssociatedWith; NameOfCoef ir; } + } + Constraint { + { NameOfCoef Uz ; EntityType Region ; NameOfConstraint Voltage_Cir ; } + { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; } + } + } + +} + + +Formulation { + { Name dynamic; Type FemEquation; + Quantity { + { Name V; Type Local; NameOfSpace Hgrad_V; } + { Name U; Type Global; NameOfSpace Hgrad_V [U]; } + { Name I; Type Global; NameOfSpace Hgrad_V [I]; } + { Name Uz; Type Global; NameOfSpace Hregion_Cir [Uz]; } + { Name Iz; Type Global; NameOfSpace Hregion_Cir [Iz]; } + } + Equation { + // FEM domain + Integral { [ kappa[] * Dof{d V}, {d V} ]; In Vol_Ele; + Integration I1; Jacobian JVol; } + GlobalTerm{ [ Dof{I}, {U} ]; In Sur_Ele; } + + // Circuit related terms + // Resistance equation + GlobalTerm{ [ Dof{Uz}, {Iz} ]; In Resistance_Cir; } + GlobalTerm{ [ R[] * Dof{Iz}, {Iz} ]; In Resistance_Cir; } + + // Inductance equation + GlobalTerm{ [ Dof{Uz}, {Iz} ]; In Inductance_Cir; } + GlobalTerm{ DtDof[ L[] * Dof{Iz}, {Iz} ]; In Inductance_Cir; } + + // Capacitance equation + GlobalTerm{ [ Dof{Iz}, {Iz} ]; In Capacitance_Cir; } + GlobalTerm{ DtDof[ C[] * Dof{Uz}, {Iz} ]; In Capacitance_Cir; } + + // Inserting the network + GlobalEquation { Type Network; NameOfConstraint ElectricalCircuit; + { Node {I}; Loop {U}; Equation {I}; In Sur_Ele; } + { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } + } + } + } +} + +Resolution { + { Name dynamic; + System { + { Name A; NameOfFormulation dynamic; } + } + Operation { + InitSolution[A]; + TimeLoopTheta[0.0, tStop, tStep, 1.0]{ + Generate[A]; + Solve[A]; + Test[SaveFct[]] { SaveSolution[A]; } + } + } + } +} + +PostProcessing { + { Name Ele; NameOfFormulation dynamic; + Quantity { + { Name V; Value{ Local{ [ {V} ]; In Vol_Ele; Jacobian JVol;} } } + { Name Jv; Value{ Local{ [ -kappa[]*{d V} ]; In Vol_Ele; Jacobian JVol;} } } + { Name J; Value{ Local{ [ Norm[kappa[]*{d V}] ]; In Vol_Ele; Jacobian JVol;} } } + { Name U; Value { Term { [ {U} ]; In Sur_Ele; } } } + // The minus sign here is for getting positive currents at the top of the + // cubes. This is because incomming currents are negative. + { Name I; Value { Term { [ -{I} ]; In Sur_Ele; } } } + } + } +} + +PostOperation { + // Absolute voltage everywhere [V] + { Name V; NameOfPostProcessing Ele; + Operation { + Print[ V, OnElementsOf Vol_Ele, TimeLegend, File "Result_V.pos"]; + } + } + // Current through the top surfaces of the cubes [A] + { Name I_Top; NameOfPostProcessing Ele; + Operation { + Print[ I, OnElementsOf Region[{Top1, Top2, Top3}], TimeLegend, + File "Result_I_Top.pos"]; + } + } + // Current density vectors everywhere [A/m^2] + { Name J_vectors; NameOfPostProcessing Ele; + Operation { + Print[ Jv, OnElementsOf Vol_Ele, TimeLegend, File "Result_J_vectors.pos"]; + } + } + // Magnitude of current density everywhere [A/m^2] + { Name J_magnitude; NameOfPostProcessing Ele; + Operation { + Print[ J, OnElementsOf Vol_Ele, TimeLegend, File "Result_J.pos"]; + } + } + // Store the results in an ASCII file + { Name Cube_Top_Values_ASCII; NameOfPostProcessing Ele; + Operation { + Print[U, OnRegion Top1, File "Result_Cube1TopValues.txt", Format TimeTable]; + Print[U, OnRegion Top2, File "Result_Cube2TopValues.txt", Format TimeTable]; + Print[U, OnRegion Top3, File "Result_Cube3TopValues.txt", Format TimeTable]; + + Print[I, OnRegion Top1, File > "Result_Cube1TopValues.txt", Format TimeTable]; + Print[I, OnRegion Top2, File > "Result_Cube2TopValues.txt", Format TimeTable]; + Print[I, OnRegion Top3, File > "Result_Cube3TopValues.txt", Format TimeTable]; + } + } + +} diff --git a/CircuitCoupling/RLC_circuit_common.pro b/CircuitCoupling/RLC_circuit_common.pro index cfa9d02..65360ad 100644 --- a/CircuitCoupling/RLC_circuit_common.pro +++ b/CircuitCoupling/RLC_circuit_common.pro @@ -1,12 +1,12 @@ -// Physical numbers for volumes -Cube1 = 1001; -Cube2 = 1002; -Cube3 = 1003; - -// Physical numbers for surfaces -Cube1Top = 2001; -Cube1Bottom = 2002; -Cube2Top = 2003; -Cube2Bottom = 2004; -Cube3Top = 2005; -Cube3Bottom = 2006; +// Physical numbers for volumes +Cube1 = 1001; +Cube2 = 1002; +Cube3 = 1003; + +// Physical numbers for surfaces +Cube1Top = 2001; +Cube1Bottom = 2002; +Cube2Top = 2003; +Cube2Bottom = 2004; +Cube3Top = 2005; +Cube3Bottom = 2006; diff --git a/CircuitCoupling/R_circuit.geo b/CircuitCoupling/R_circuit.geo index 77d9838..dad9c9a 100644 --- a/CircuitCoupling/R_circuit.geo +++ b/CircuitCoupling/R_circuit.geo @@ -1,39 +1,39 @@ -// Just 4 cubes - -Include "R_circuit_common.pro"; - -lc = 0.25; // Cjaracteristic length - -Point(1) = {0, 0, 0, lc}; -Extrude {1, 0, 0} { - Point{1}; -} -Extrude {0, 1, 0} { - Line{1}; // Layers{10}; Recombine; -} -Extrude {0, 0, 1} { - Surface{5}; // Layers{10}; Recombine; -} -Translate {2, 0, 0} { - Duplicata { Volume{1}; } -} -Translate {0, 4, 0} { - Duplicata { Volume{1}; } -} -Translate {2, 4, 0} { - Duplicata { Volume{1}; } -} - -Physical Surface(Cube1Top) = {27}; -Physical Surface(Cube1Bottom) = {5}; -Physical Surface(Cube2Top) = {34}; -Physical Surface(Cube2Bottom) = {29}; -Physical Surface(Cube3Top) = {61}; -Physical Surface(Cube3Bottom) = {56}; -Physical Surface(Cube4Top) = {88}; -Physical Surface(Cube4Bottom) = {83}; - -Physical Volume(Cube1) = {1}; -Physical Volume(Cube2) = {28}; -Physical Volume(Cube3) = {55}; -Physical Volume(Cube4) = {82}; +// Just 4 cubes + +Include "R_circuit_common.pro"; + +lc = 0.25; // Cjaracteristic length + +Point(1) = {0, 0, 0, lc}; +Extrude {1, 0, 0} { + Point{1}; +} +Extrude {0, 1, 0} { + Line{1}; // Layers{10}; Recombine; +} +Extrude {0, 0, 1} { + Surface{5}; // Layers{10}; Recombine; +} +Translate {2, 0, 0} { + Duplicata { Volume{1}; } +} +Translate {0, 4, 0} { + Duplicata { Volume{1}; } +} +Translate {2, 4, 0} { + Duplicata { Volume{1}; } +} + +Physical Surface(Cube1Top) = {27}; +Physical Surface(Cube1Bottom) = {5}; +Physical Surface(Cube2Top) = {34}; +Physical Surface(Cube2Bottom) = {29}; +Physical Surface(Cube3Top) = {61}; +Physical Surface(Cube3Bottom) = {56}; +Physical Surface(Cube4Top) = {88}; +Physical Surface(Cube4Bottom) = {83}; + +Physical Volume(Cube1) = {1}; +Physical Volume(Cube2) = {28}; +Physical Volume(Cube3) = {55}; +Physical Volume(Cube4) = {82}; diff --git a/CircuitCoupling/R_circuit.pro b/CircuitCoupling/R_circuit.pro index f418c3c..a8ff7cb 100644 --- a/CircuitCoupling/R_circuit.pro +++ b/CircuitCoupling/R_circuit.pro @@ -1,342 +1,342 @@ -/* ------------------------------------------------------------------- - Tutorial 8a : circuit coupling - resistive circuit - - Features: - - Electrokinetic formulation coupled with resistive circuit - - Definition of circuit elements (sources, resistances) - - Implementation of a netlist - - To compute the solution in a terminal: - getdp R_circuit -solve static -pos Cube_Top_Values_ASCII - - To compute the solution interactively from the Gmsh GUI: - File > Open > R_circuit.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* - This example shows how to implement a circuit with discrete elements in a - finite element simulation. Only lumped resistors, voltage- and current-sources - are used. There are four separate cubes, each with a certain conductivity. The - bottom of all cubes is kept at a constant voltage via the constraint - Voltage_3D. The top of the cubes are connected with a circuit according the - `R_circuit.jpg' schematic. -*/ - -Include "R_circuit_common.pro"; - -// FEM domain group data -Group { - // Surfaces - Top1 = Region[Cube1Top]; - Bottom1 = Region[Cube1Bottom]; - Top2 = Region[Cube2Top]; - Bottom2 = Region[Cube2Bottom]; - Top3 = Region[Cube3Top]; - Bottom3 = Region[Cube3Bottom]; - Top4 = Region[Cube4Top]; - Bottom4 = Region[Cube4Bottom]; - - // Volumes - Cube1 = Region[Cube1]; - Cube2 = Region[Cube2]; - Cube3 = Region[Cube3]; - Cube4 = Region[Cube4]; - - // FEM Electrical regions - // * all volumes: - Vol_Ele = Region[{Cube1, Cube2, Cube3, Cube4}]; - // * all surfaces connected to the lumped element circuit - Sur_Ele = Region[{Top1, Bottom1, Top2, Bottom2, Top3, Bottom3, Top4, Bottom4}]; - // * total electrical computation domain: - Dom_Ele = Region[{Vol_Ele, Sur_Ele}]; -} - -// Circuit group data (fictive regions for the circuit elements) -Group { - // Sources - CurrentSource1 = Region[{3001}]; - VoltageSource1 = Region[{3002}]; - - SourceI_Cir = Region[{CurrentSource1}]; // all current sources - SourceV_Cir = Region[{VoltageSource1}]; // all voltage sources - Sources_Cir = Region[{SourceI_Cir, SourceV_Cir}]; - - // Resistors - Res1 = Region[{4001}]; - Res2 = Region[{4002}]; - Res3 = Region[{4003}]; - Res4 = Region[{4004}]; - - Resistance_Cir = Region[{Res1, Res2, Res3, Res4}]; // All resistors - - // Complete circuit domain containing all circuit elements - Domain_Cir = Region[{Resistance_Cir, SourceI_Cir, SourceV_Cir}]; -} - -// FEM domain function data -Function { - // Absolute voltage at the bottom of all cubes; set via constraint Voltage_3D, - // not via a voltage source - Vbottom = 4.0; - - // Geometry of a cube - w = 1.0; // Width [m] - l = 1.0; // Length [m] - h = 1.0; // Height [m] - - // Resistance - Rcube1 = 20.0; // Resistance of cube 1 [Ohm] - Rcube2 = 40.0; // Resistance of cube 2 [Ohm] - Rcube3 = 60.0; // Resistance of cube 3 [Ohm] - Rcube4 = 10.0; // Resistance of cube 4 [Ohm] - - // Specific electrical conductivity [S*m/m^2] - kappa[Cube1] = h / (w * l * Rcube1); - kappa[Cube2] = h / (w * l * Rcube2); - kappa[Cube3] = h / (w * l * Rcube3); - kappa[Cube4] = h / (w * l * Rcube4); -} - -// Circuit domain function data -Function { - // External impedances functions - R[Res1] = 10.0; - R[Res2] = 20.0; - R[Res3] = 15.0; - R[Res4] = 10.0; -} - -// FEM domain constraint data -Constraint { - { Name Current_3D ; Type Assign ; - Case { - } - } - { Name Voltage_3D ; Type Assign ; - Case { - { Region Bottom1; Type Assign; Value Vbottom; } - { Region Bottom2; Type Assign; Value Vbottom; } - { Region Bottom3; Type Assign; Value Vbottom; } - { Region Bottom4; Type Assign; Value Vbottom; } - } - } -} - -// Circuit domain constraint data -Constraint { - { Name Current_Cir ; - Case { - { Region CurrentSource1; Value 1.0; } // CurrentSource1 has 1.0 A - } - } - { Name Voltage_Cir ; - Case { - { Region VoltageSource1; Value 10.0; } // VoltageSource1 has 10.0 V - } - } - { Name ElectricalCircuit ; Type Network ; - Case Circuit1 { - // Here the circuit netlist is implemented. The important thing is that - // each surface of the 3D geometry which is connected to the circuit - // (Sur_Ele) has a single voltage and current, but in the netlist they - // appear with two terminals (two nodes). The voltage between the two - // nodes corresponds to the absolute voltage of the surface. The current - // through the two nodes is the current flowing through the surface. In - // this simple case here we need the voltage drop across a cube (e.g. cube - // 1) in the netlist rather than the absolute voltage. Therefore the - // bottom-voltage has to be subtracted from the top-voltage. This is - // accomplished by connecting both surfaces anti-serial (e.g. at node 4; - // The voltage drop across cube 1 is then between node 2 and node 10). - - { Region VoltageSource1; Branch{1, 10}; } - { Region Res1; Branch{1, 2}; } - // Voltage between node 2 and node 4 corresponds to the absolute voltage - // of Top1: - { Region Top1; Branch{2, 4}; } - // Note the reverse order of the nodes here - it's for subtracting the - // bottom voltage: - { Region Bottom1; Branch{10, 4}; } - // Voltage between node 3 and node 5 corresponds to the absolute voltage - // of Top2: - { Region Res2; Branch{2, 3}; } - { Region Top2; Branch{3, 5}; } - // Note the reverse order of the nodes here! It's for subtracting the - // bottom voltage.: - { Region Bottom2; Branch{10, 5}; } - - { Region CurrentSource1; Branch{6, 10}; } - { Region Res3; Branch{6, 10}; } - // Voltage between node 6 and node 8 corresponds to the absolute voltage - // of Top3: - { Region Top3; Branch{6, 8}; } - // Note the reverse order of the nodes here! It's for subtracting the - // bottom voltage.: - { Region Bottom3; Branch{10, 8}; } - { Region Res4; Branch{6, 7}; } - // Voltage between node 7 and node 9 corresponds to the absolute voltage - // of Top4: - { Region Top4; Branch{7, 9}; } - // Note the reverse order of the nodes here! It's for subtracting the - // bottom voltage: - { Region Bottom4; Branch{10, 9}; } - } - } -} - -Jacobian { - { Name JVol ; - Case { - { Region Region[{Vol_Ele}]; Jacobian Vol; } - { Region Region[{Sur_Ele}]; Jacobian Sur; } - } - } -} - -Integration { - { Name I1 ; - Case { - { Type Gauss ; - Case { - { GeoElement Point ; NumberOfPoints 1 ; } - { GeoElement Line ; NumberOfPoints 5 ; } - { GeoElement Triangle ; NumberOfPoints 6 ; } - { GeoElement Quadrangle ; NumberOfPoints 7 ; } - { GeoElement Tetrahedron ; NumberOfPoints 15 ; } - { GeoElement Hexahedron ; NumberOfPoints 34 ; } - { GeoElement Prism ; NumberOfPoints 21 ; } - } - } - } - } -} - - -FunctionSpace { - { Name Hgrad_V; Type Form0; - BasisFunction { - // All nodes but the grouped nodes of the surfaces for connecting the - // circuitry - { Name sn; NameOfCoef vn; Function BF_Node; - Support Dom_Ele; Entity NodesOf[ All, Not Sur_Ele ]; } - // Grouped nodes: Each surface of Sur_Ele has just one single voltage -> - // each surface is just one node effectively - { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; - Support Dom_Ele; Entity GroupsOfNodesOf[ Sur_Ele ]; } - } - GlobalQuantity { - // Voltage of the surfaces of Sur_Ele - { Name U; Type AliasOf; NameOfCoef vf; } - // Current flowing through the surfaces - { Name I; Type AssociatedWith; NameOfCoef vf; } - } - Constraint { - { NameOfCoef vn; EntityType NodesOf ; NameOfConstraint Voltage_3D; } - { NameOfCoef U; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage_3D; } - { NameOfCoef I; EntityType GroupsOfNodesOf ; NameOfConstraint Current_3D; } - } - } - - { Name Hregion_Cir; Type Scalar; - BasisFunction { - { Name sn; NameOfCoef ir; Function BF_Region; - Support Domain_Cir; Entity Domain_Cir; } - } - GlobalQuantity { - { Name Iz; Type AliasOf; NameOfCoef ir; } - { Name Uz; Type AssociatedWith; NameOfCoef ir; } - } - Constraint { - { NameOfCoef Uz ; EntityType Region ; NameOfConstraint Voltage_Cir ; } - { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; } - } - } -} - -Formulation { - { Name static; Type FemEquation; - Quantity { - { Name V; Type Local; NameOfSpace Hgrad_V; } - { Name U; Type Global; NameOfSpace Hgrad_V [U]; } - { Name I; Type Global; NameOfSpace Hgrad_V [I]; } - { Name Uz; Type Global; NameOfSpace Hregion_Cir [Uz]; } - { Name Iz; Type Global; NameOfSpace Hregion_Cir [Iz]; } - } - Equation { - // FEM domain - Integral { [ kappa[] * Dof{d V}, {d V} ]; - In Vol_Ele; Integration I1; Jacobian JVol; } - GlobalTerm { [ Dof{I} , {U} ]; In Sur_Ele; } - - // Circuit related terms: Resistance equation - GlobalTerm { [ Dof{Uz}, {Iz} ]; In Resistance_Cir; } - GlobalTerm { [ R[] * Dof{Iz}, {Iz} ]; In Resistance_Cir; } - - // Here is the connection between the circuit and the finite element simulation - GlobalEquation { Type Network; NameOfConstraint ElectricalCircuit; - { Node {I}; Loop {U}; Equation {I}; In Sur_Ele; } - { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } - } - } - } -} - -Resolution { - { Name static; - System { - { Name A; NameOfFormulation static; } - } - Operation { - Generate[A]; - Solve[A]; - SaveSolution[A]; - } - } -} - -PostProcessing { - { Name Ele; NameOfFormulation static; - Quantity { - { Name V; Value{ Local{ [ {V} ]; In Vol_Ele; Jacobian JVol;} } } - { Name Jv; Value{ Local{ [ -kappa[]*{d V} ]; In Vol_Ele; Jacobian JVol;} } } - { Name J; Value{ Local{ [ Norm[kappa[]*{d V}] ]; In Vol_Ele; Jacobian JVol;} } } - { Name U; Value { Term { [ {U} ]; In Sur_Ele; } } } - { Name I; Value { Term { [ {I} ]; In Sur_Ele; } } } - } - } -} - -PostOperation { - // Absolute voltage [V] - { Name V; NameOfPostProcessing Ele; - Operation { - Print[ V, OnElementsOf Vol_Ele, File "Result_V.pos"]; - } - } - // Current density vectors [A/m^2] - { Name J_vectors; NameOfPostProcessing Ele; - Operation { - Print[ Jv, OnElementsOf Vol_Ele, File "Result_J_vectors.pos"]; - } - } - // Magnitude of current density [A/m^2] - { Name J_magnitude; NameOfPostProcessing Ele; - Operation { - Print[ J, OnElementsOf Vol_Ele, File "Result_J.pos"]; - } - } - // Store the results in an ASCII file - { Name Cube_Top_Values_ASCII; NameOfPostProcessing Ele; - Operation { - Print[U, OnRegion Top1, File "Result_CubeTopValues.txt", Format SimpleTable]; - Print[U, OnRegion Top2, File > "Result_CubeTopValues.txt", Format SimpleTable]; - Print[U, OnRegion Top3, File > "Result_CubeTopValues.txt", Format SimpleTable]; - Print[U, OnRegion Top4, File > "Result_CubeTopValues.txt", Format SimpleTable]; - - Print[I, OnRegion Top1, File > "Result_CubeTopValues.txt", Format SimpleTable]; - Print[I, OnRegion Top2, File > "Result_CubeTopValues.txt", Format SimpleTable]; - Print[I, OnRegion Top3, File > "Result_CubeTopValues.txt", Format SimpleTable]; - Print[I, OnRegion Top4, File > "Result_CubeTopValues.txt", Format SimpleTable]; - } - } -} +/* ------------------------------------------------------------------- + Tutorial 8a : circuit coupling - resistive circuit + + Features: + - Electrokinetic formulation coupled with resistive circuit + - Definition of circuit elements (sources, resistances) + - Implementation of a netlist + + To compute the solution in a terminal: + getdp R_circuit -solve static -pos Cube_Top_Values_ASCII + + To compute the solution interactively from the Gmsh GUI: + File > Open > R_circuit.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* + This example shows how to implement a circuit with discrete elements in a + finite element simulation. Only lumped resistors, voltage- and current-sources + are used. There are four separate cubes, each with a certain conductivity. The + bottom of all cubes is kept at a constant voltage via the constraint + Voltage_3D. The top of the cubes are connected with a circuit according the + `R_circuit.jpg' schematic. +*/ + +Include "R_circuit_common.pro"; + +// FEM domain group data +Group { + // Surfaces + Top1 = Region[Cube1Top]; + Bottom1 = Region[Cube1Bottom]; + Top2 = Region[Cube2Top]; + Bottom2 = Region[Cube2Bottom]; + Top3 = Region[Cube3Top]; + Bottom3 = Region[Cube3Bottom]; + Top4 = Region[Cube4Top]; + Bottom4 = Region[Cube4Bottom]; + + // Volumes + Cube1 = Region[Cube1]; + Cube2 = Region[Cube2]; + Cube3 = Region[Cube3]; + Cube4 = Region[Cube4]; + + // FEM Electrical regions + // * all volumes: + Vol_Ele = Region[{Cube1, Cube2, Cube3, Cube4}]; + // * all surfaces connected to the lumped element circuit + Sur_Ele = Region[{Top1, Bottom1, Top2, Bottom2, Top3, Bottom3, Top4, Bottom4}]; + // * total electrical computation domain: + Dom_Ele = Region[{Vol_Ele, Sur_Ele}]; +} + +// Circuit group data (fictive regions for the circuit elements) +Group { + // Sources + CurrentSource1 = Region[{3001}]; + VoltageSource1 = Region[{3002}]; + + SourceI_Cir = Region[{CurrentSource1}]; // all current sources + SourceV_Cir = Region[{VoltageSource1}]; // all voltage sources + Sources_Cir = Region[{SourceI_Cir, SourceV_Cir}]; + + // Resistors + Res1 = Region[{4001}]; + Res2 = Region[{4002}]; + Res3 = Region[{4003}]; + Res4 = Region[{4004}]; + + Resistance_Cir = Region[{Res1, Res2, Res3, Res4}]; // All resistors + + // Complete circuit domain containing all circuit elements + Domain_Cir = Region[{Resistance_Cir, SourceI_Cir, SourceV_Cir}]; +} + +// FEM domain function data +Function { + // Absolute voltage at the bottom of all cubes; set via constraint Voltage_3D, + // not via a voltage source + Vbottom = 4.0; + + // Geometry of a cube + w = 1.0; // Width [m] + l = 1.0; // Length [m] + h = 1.0; // Height [m] + + // Resistance + Rcube1 = 20.0; // Resistance of cube 1 [Ohm] + Rcube2 = 40.0; // Resistance of cube 2 [Ohm] + Rcube3 = 60.0; // Resistance of cube 3 [Ohm] + Rcube4 = 10.0; // Resistance of cube 4 [Ohm] + + // Specific electrical conductivity [S*m/m^2] + kappa[Cube1] = h / (w * l * Rcube1); + kappa[Cube2] = h / (w * l * Rcube2); + kappa[Cube3] = h / (w * l * Rcube3); + kappa[Cube4] = h / (w * l * Rcube4); +} + +// Circuit domain function data +Function { + // External impedances functions + R[Res1] = 10.0; + R[Res2] = 20.0; + R[Res3] = 15.0; + R[Res4] = 10.0; +} + +// FEM domain constraint data +Constraint { + { Name Current_3D ; Type Assign ; + Case { + } + } + { Name Voltage_3D ; Type Assign ; + Case { + { Region Bottom1; Type Assign; Value Vbottom; } + { Region Bottom2; Type Assign; Value Vbottom; } + { Region Bottom3; Type Assign; Value Vbottom; } + { Region Bottom4; Type Assign; Value Vbottom; } + } + } +} + +// Circuit domain constraint data +Constraint { + { Name Current_Cir ; + Case { + { Region CurrentSource1; Value 1.0; } // CurrentSource1 has 1.0 A + } + } + { Name Voltage_Cir ; + Case { + { Region VoltageSource1; Value 10.0; } // VoltageSource1 has 10.0 V + } + } + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + // Here the circuit netlist is implemented. The important thing is that + // each surface of the 3D geometry which is connected to the circuit + // (Sur_Ele) has a single voltage and current, but in the netlist they + // appear with two terminals (two nodes). The voltage between the two + // nodes corresponds to the absolute voltage of the surface. The current + // through the two nodes is the current flowing through the surface. In + // this simple case here we need the voltage drop across a cube (e.g. cube + // 1) in the netlist rather than the absolute voltage. Therefore the + // bottom-voltage has to be subtracted from the top-voltage. This is + // accomplished by connecting both surfaces anti-serial (e.g. at node 4; + // The voltage drop across cube 1 is then between node 2 and node 10). + + { Region VoltageSource1; Branch{1, 10}; } + { Region Res1; Branch{1, 2}; } + // Voltage between node 2 and node 4 corresponds to the absolute voltage + // of Top1: + { Region Top1; Branch{2, 4}; } + // Note the reverse order of the nodes here - it's for subtracting the + // bottom voltage: + { Region Bottom1; Branch{10, 4}; } + // Voltage between node 3 and node 5 corresponds to the absolute voltage + // of Top2: + { Region Res2; Branch{2, 3}; } + { Region Top2; Branch{3, 5}; } + // Note the reverse order of the nodes here! It's for subtracting the + // bottom voltage.: + { Region Bottom2; Branch{10, 5}; } + + { Region CurrentSource1; Branch{6, 10}; } + { Region Res3; Branch{6, 10}; } + // Voltage between node 6 and node 8 corresponds to the absolute voltage + // of Top3: + { Region Top3; Branch{6, 8}; } + // Note the reverse order of the nodes here! It's for subtracting the + // bottom voltage.: + { Region Bottom3; Branch{10, 8}; } + { Region Res4; Branch{6, 7}; } + // Voltage between node 7 and node 9 corresponds to the absolute voltage + // of Top4: + { Region Top4; Branch{7, 9}; } + // Note the reverse order of the nodes here! It's for subtracting the + // bottom voltage: + { Region Bottom4; Branch{10, 9}; } + } + } +} + +Jacobian { + { Name JVol ; + Case { + { Region Region[{Vol_Ele}]; Jacobian Vol; } + { Region Region[{Sur_Ele}]; Jacobian Sur; } + } + } +} + +Integration { + { Name I1 ; + Case { + { Type Gauss ; + Case { + { GeoElement Point ; NumberOfPoints 1 ; } + { GeoElement Line ; NumberOfPoints 5 ; } + { GeoElement Triangle ; NumberOfPoints 6 ; } + { GeoElement Quadrangle ; NumberOfPoints 7 ; } + { GeoElement Tetrahedron ; NumberOfPoints 15 ; } + { GeoElement Hexahedron ; NumberOfPoints 34 ; } + { GeoElement Prism ; NumberOfPoints 21 ; } + } + } + } + } +} + + +FunctionSpace { + { Name Hgrad_V; Type Form0; + BasisFunction { + // All nodes but the grouped nodes of the surfaces for connecting the + // circuitry + { Name sn; NameOfCoef vn; Function BF_Node; + Support Dom_Ele; Entity NodesOf[ All, Not Sur_Ele ]; } + // Grouped nodes: Each surface of Sur_Ele has just one single voltage -> + // each surface is just one node effectively + { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; + Support Dom_Ele; Entity GroupsOfNodesOf[ Sur_Ele ]; } + } + GlobalQuantity { + // Voltage of the surfaces of Sur_Ele + { Name U; Type AliasOf; NameOfCoef vf; } + // Current flowing through the surfaces + { Name I; Type AssociatedWith; NameOfCoef vf; } + } + Constraint { + { NameOfCoef vn; EntityType NodesOf ; NameOfConstraint Voltage_3D; } + { NameOfCoef U; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage_3D; } + { NameOfCoef I; EntityType GroupsOfNodesOf ; NameOfConstraint Current_3D; } + } + } + + { Name Hregion_Cir; Type Scalar; + BasisFunction { + { Name sn; NameOfCoef ir; Function BF_Region; + Support Domain_Cir; Entity Domain_Cir; } + } + GlobalQuantity { + { Name Iz; Type AliasOf; NameOfCoef ir; } + { Name Uz; Type AssociatedWith; NameOfCoef ir; } + } + Constraint { + { NameOfCoef Uz ; EntityType Region ; NameOfConstraint Voltage_Cir ; } + { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; } + } + } +} + +Formulation { + { Name static; Type FemEquation; + Quantity { + { Name V; Type Local; NameOfSpace Hgrad_V; } + { Name U; Type Global; NameOfSpace Hgrad_V [U]; } + { Name I; Type Global; NameOfSpace Hgrad_V [I]; } + { Name Uz; Type Global; NameOfSpace Hregion_Cir [Uz]; } + { Name Iz; Type Global; NameOfSpace Hregion_Cir [Iz]; } + } + Equation { + // FEM domain + Integral { [ kappa[] * Dof{d V}, {d V} ]; + In Vol_Ele; Integration I1; Jacobian JVol; } + GlobalTerm { [ Dof{I} , {U} ]; In Sur_Ele; } + + // Circuit related terms: Resistance equation + GlobalTerm { [ Dof{Uz}, {Iz} ]; In Resistance_Cir; } + GlobalTerm { [ R[] * Dof{Iz}, {Iz} ]; In Resistance_Cir; } + + // Here is the connection between the circuit and the finite element simulation + GlobalEquation { Type Network; NameOfConstraint ElectricalCircuit; + { Node {I}; Loop {U}; Equation {I}; In Sur_Ele; } + { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } + } + } + } +} + +Resolution { + { Name static; + System { + { Name A; NameOfFormulation static; } + } + Operation { + Generate[A]; + Solve[A]; + SaveSolution[A]; + } + } +} + +PostProcessing { + { Name Ele; NameOfFormulation static; + Quantity { + { Name V; Value{ Local{ [ {V} ]; In Vol_Ele; Jacobian JVol;} } } + { Name Jv; Value{ Local{ [ -kappa[]*{d V} ]; In Vol_Ele; Jacobian JVol;} } } + { Name J; Value{ Local{ [ Norm[kappa[]*{d V}] ]; In Vol_Ele; Jacobian JVol;} } } + { Name U; Value { Term { [ {U} ]; In Sur_Ele; } } } + { Name I; Value { Term { [ {I} ]; In Sur_Ele; } } } + } + } +} + +PostOperation { + // Absolute voltage [V] + { Name V; NameOfPostProcessing Ele; + Operation { + Print[ V, OnElementsOf Vol_Ele, File "Result_V.pos"]; + } + } + // Current density vectors [A/m^2] + { Name J_vectors; NameOfPostProcessing Ele; + Operation { + Print[ Jv, OnElementsOf Vol_Ele, File "Result_J_vectors.pos"]; + } + } + // Magnitude of current density [A/m^2] + { Name J_magnitude; NameOfPostProcessing Ele; + Operation { + Print[ J, OnElementsOf Vol_Ele, File "Result_J.pos"]; + } + } + // Store the results in an ASCII file + { Name Cube_Top_Values_ASCII; NameOfPostProcessing Ele; + Operation { + Print[U, OnRegion Top1, File "Result_CubeTopValues.txt", Format SimpleTable]; + Print[U, OnRegion Top2, File > "Result_CubeTopValues.txt", Format SimpleTable]; + Print[U, OnRegion Top3, File > "Result_CubeTopValues.txt", Format SimpleTable]; + Print[U, OnRegion Top4, File > "Result_CubeTopValues.txt", Format SimpleTable]; + + Print[I, OnRegion Top1, File > "Result_CubeTopValues.txt", Format SimpleTable]; + Print[I, OnRegion Top2, File > "Result_CubeTopValues.txt", Format SimpleTable]; + Print[I, OnRegion Top3, File > "Result_CubeTopValues.txt", Format SimpleTable]; + Print[I, OnRegion Top4, File > "Result_CubeTopValues.txt", Format SimpleTable]; + } + } +} diff --git a/CircuitCoupling/R_circuit_common.pro b/CircuitCoupling/R_circuit_common.pro index 80415a6..9d34d50 100644 --- a/CircuitCoupling/R_circuit_common.pro +++ b/CircuitCoupling/R_circuit_common.pro @@ -1,15 +1,15 @@ -// Physical numbers for volumes -Cube1 = 1001; -Cube2 = 1002; -Cube3 = 1003; -Cube4 = 1004; - -// Physical numbers for surfaces -Cube1Top = 2001; -Cube1Bottom = 2002; -Cube2Top = 2003; -Cube2Bottom = 2004; -Cube3Top = 2005; -Cube3Bottom = 2006; -Cube4Top = 2007; -Cube4Bottom = 2008; +// Physical numbers for volumes +Cube1 = 1001; +Cube2 = 1002; +Cube3 = 1003; +Cube4 = 1004; + +// Physical numbers for surfaces +Cube1Top = 2001; +Cube1Bottom = 2002; +Cube2Top = 2003; +Cube2Bottom = 2004; +Cube3Top = 2005; +Cube3Bottom = 2006; +Cube4Top = 2007; +Cube4Bottom = 2008; diff --git a/Elasticity/wrench2D.geo b/Elasticity/wrench2D.geo index d107af1..782b701 100644 --- a/Elasticity/wrench2D.geo +++ b/Elasticity/wrench2D.geo @@ -1,72 +1,72 @@ - -Include "wrench2D_common.pro"; - -Solver.AutoMesh = 2; - -lc = Refine; -lc2 = lc; // nut region -lc3 = lc/5; // edge grip region - -Ri = 0.494*in; -Re = 0.8*in; -L = LLength; -LL = 1*in; -E = 0.625*in; -F = Width; -D = 0.45*in; // Nut - -theta = Inclination; - -Point(1) = { 0, 0, 0, lc2}; -Point(2) = { -Ri, 0, 0, lc2}; -th1 = Asin[E/2./Ri]; -Point(3) = { -Ri + Ri*Cos[th1], Ri*Sin[th1], 0, lc2}; -th2 = Asin[E/2./Re]; -Point(4) = { -Re*Cos[th2]+D, Re*Sin[th2], 0, lc3}; -Point(5) = { -Re*Cos[th2], Re*Sin[th2], 0, lc2}; -th3 = th2 - theta; -Point(6) = { Re*Cos[th3], Re*Sin[th3], 0, lc}; -Point(7) = { (L-LL)*Cos[theta]+F/2.*Sin[theta], - -(L-LL)*Sin[theta]+F/2.*Cos[theta], 0, lc}; -Point(8) = { L*Cos[theta]+F/2.*Sin[theta], - -L*Sin[theta]+F/2.*Cos[theta], 0, lc}; -Point(9) = { L*Cos[theta]-F/2.*Sin[theta], - -L*Sin[theta]-F/2.*Cos[theta], 0, lc}; -th4 = -th2 - theta; -Point(10) = { Re*Cos[th4], Re*Sin[th4], 0, lc}; -Point(11) = { -Re*Cos[th2], -Re*Sin[th2], 0, lc2}; -Point(12) = { -Re*Cos[th2]+D, -Re*Sin[th2], 0, lc3}; -Point(13) = { -Ri + Ri*Cos[th1], -Ri*Sin[th1], 0, lc2}; - -contour[] = {}; -contour[] += newl; Circle(newl) = {1,2,3}; -contour[] += newl; Line(newl) = {3,4}; -contour[] += newl; cl1=newl; Line(newl) = {4,5}; -contour[] += newl; Circle(newl) = {5,1,6}; -contour[] += newl; Line(newl) = {6,7}; -contour[] += newl; cl2=newl; Line(newl) = {7,8}; -contour[] += newl; Line(newl) = {8,9}; -contour[] += newl; Line(newl) = {9,10}; -contour[] += newl; Circle(newl) = {10,1,11}; -contour[] += newl; cl3=newl; Line(newl) = {11,12}; -contour[] += newl; Line(newl) = {12,13}; -contour[] += newl; Circle(newl) = {13,2,1}; -ll=newll; Line Loop(ll) = { contour[] }; - -wrench=news; Plane Surface(wrench) = {-ll}; - -/* Using quadrangular elements instead of triangular elements is pretty simple. - You just have to invoke the Recombine command at this place. - GetDP deals will all the rest by itself. - */ -If(Recomb==1) - Recombine Surface{wrench}; -EndIf - -Physical Surface(1)= wrench; -Physical Line(2)= {cl1, cl3}; -Physical Line(3)= {cl2}; - - - - + +Include "wrench2D_common.pro"; + +Solver.AutoMesh = 2; + +lc = Refine; +lc2 = lc; // nut region +lc3 = lc/5; // edge grip region + +Ri = 0.494*in; +Re = 0.8*in; +L = LLength; +LL = 1*in; +E = 0.625*in; +F = Width; +D = 0.45*in; // Nut + +theta = Inclination; + +Point(1) = { 0, 0, 0, lc2}; +Point(2) = { -Ri, 0, 0, lc2}; +th1 = Asin[E/2./Ri]; +Point(3) = { -Ri + Ri*Cos[th1], Ri*Sin[th1], 0, lc2}; +th2 = Asin[E/2./Re]; +Point(4) = { -Re*Cos[th2]+D, Re*Sin[th2], 0, lc3}; +Point(5) = { -Re*Cos[th2], Re*Sin[th2], 0, lc2}; +th3 = th2 - theta; +Point(6) = { Re*Cos[th3], Re*Sin[th3], 0, lc}; +Point(7) = { (L-LL)*Cos[theta]+F/2.*Sin[theta], + -(L-LL)*Sin[theta]+F/2.*Cos[theta], 0, lc}; +Point(8) = { L*Cos[theta]+F/2.*Sin[theta], + -L*Sin[theta]+F/2.*Cos[theta], 0, lc}; +Point(9) = { L*Cos[theta]-F/2.*Sin[theta], + -L*Sin[theta]-F/2.*Cos[theta], 0, lc}; +th4 = -th2 - theta; +Point(10) = { Re*Cos[th4], Re*Sin[th4], 0, lc}; +Point(11) = { -Re*Cos[th2], -Re*Sin[th2], 0, lc2}; +Point(12) = { -Re*Cos[th2]+D, -Re*Sin[th2], 0, lc3}; +Point(13) = { -Ri + Ri*Cos[th1], -Ri*Sin[th1], 0, lc2}; + +contour[] = {}; +contour[] += newl; Circle(newl) = {1,2,3}; +contour[] += newl; Line(newl) = {3,4}; +contour[] += newl; cl1=newl; Line(newl) = {4,5}; +contour[] += newl; Circle(newl) = {5,1,6}; +contour[] += newl; Line(newl) = {6,7}; +contour[] += newl; cl2=newl; Line(newl) = {7,8}; +contour[] += newl; Line(newl) = {8,9}; +contour[] += newl; Line(newl) = {9,10}; +contour[] += newl; Circle(newl) = {10,1,11}; +contour[] += newl; cl3=newl; Line(newl) = {11,12}; +contour[] += newl; Line(newl) = {12,13}; +contour[] += newl; Circle(newl) = {13,2,1}; +ll=newll; Line Loop(ll) = { contour[] }; + +wrench=news; Plane Surface(wrench) = {-ll}; + +/* Using quadrangular elements instead of triangular elements is pretty simple. + You just have to invoke the Recombine command at this place. + GetDP deals will all the rest by itself. + */ +If(Recomb==1) + Recombine Surface{wrench}; +EndIf + +Physical Surface(1)= wrench; +Physical Line(2)= {cl1, cl3}; +Physical Line(3)= {cl2}; + + + + diff --git a/Elasticity/wrench2D.pro b/Elasticity/wrench2D.pro index d7a27a0..76147ed 100644 --- a/Elasticity/wrench2D.pro +++ b/Elasticity/wrench2D.pro @@ -1,350 +1,350 @@ -/* ------------------------------------------------------------------- - Tutorial 3 : linear elastic model of a wrench - - Features: - - "grad u" GetDP specific formulation for linear elasticity - - first and second order elements - - triangular and quadrangular elements - - To compute the solution interactively from the Gmsh GUI: - File > Open > wrench.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* Linear elasticity with GetDP: - - GetDP has a peculiar way to deal with linear elasticity. Instead of a vector - field "u = Vector[ ux, uy, uz ]", the displacement field is regarded as two - (2D case) or 3 (3D case) scalar fields. Unlike conventional formulations - then, GetDP's formulation is written in terms of the gradient "grad u" of the - displacement field, which is a non-symmetric tensor, and the needed - symmetrization (to define the strain tensor and relate it to the stress - tensor) is done through the constitutive relationship (Hooke law). The - reason for this unusual formulation is to be able to use also for elastic - problems the powerful geometrical and homological kernel of GetDP, which - relies on the operators grad, curl and div. - - The "grad u" formulation entails a small increase of assembly work but makes - in counterpart lots of geometrical features implemented in GetDP (change of - coordinates, function spaces, etc...) applicable to elastic problems - out-of-the-box, since the scalar fields { ux, uy, uz } have exactly the same - geometrical properties as, e.g. a scalar electric potential or a temperature - field. */ - -Include "wrench2D_common.pro"; - -Young = 1e9 * DefineNumber[ 200, Name "Material/Young modulus [GPa]"]; -Poisson = DefineNumber[ 0.3, Name "Material/Poisson coefficient []"]; -AppliedForce = DefineNumber[ 100, Name "Material/Applied force [N]"]; - -// Approximation of the maximum deflection by an analytical model: -// Deflection = PL^3/(3EI) with I = Width^3*Thickness/12 -Deflection = DefineNumber[4*AppliedForce*((LLength-0.018)/Width)^3/(Young*Thickness)*1e3, - Name "Solution/Deflection (analytical) [mm]", ReadOnly 1]; - -Group { - // Physical regions: Give explicit labels to the regions defined in the .geo file - Wrench = Region[ 1 ]; - Grip = Region[ 2 ]; - Force = Region[ 3 ]; - - // Abstract regions: - Vol_Mec = Region[ Wrench ]; - Vol_Force_Mec = Region[ Wrench ]; - Sur_Clamp_Mec = Region[ Grip ]; - Sur_Force_Mec = Region[ Force ]; - - /* Signification of the abstract regions: - - Vol_Mec : Elastic domain - - Vol_Force_Mec : Region with imposed volumic force - - Sur_Force_Mec : Surface with imposed surface traction - - Sur_Clamp_Mec : Surface with imposed zero displacements (all components) */ -} - -Function { - /* Material coefficients. - No need to define them regionwise here ( E[{Wrench}] = ... ; ) - as there is only one region in this model. */ - E[] = Young; - nu[] = Poisson; - /* Components of the volumic force applied to the region "Vol_Force_Mec" - Gravity could be defined here ( force_y[] = 7000*9.81; ) ; */ - force_x[] = 0; - force_y[] = 0; - /* Components of the surface traction force applied to the region "Sur_Force_Mec" */ - pressure_x[] = 0; - pressure_y[] = -AppliedForce/(SurfaceArea[]*Thickness); // downward vertical force -} - -/* Hooke's law - - The material law - - sigma_ij = C_ijkl epsilon_ij - - is represented in 2D by 4 2x2 tensors C_ij[], i,j=1,2, depending on the Lamé - coefficients of the isotropic linear material, - - lambda = E[]*nu[]/(1.+nu[])/(1.-2.*nu[]) - mu = E[]/2./(1.+nu[]) - - as follows - - EPC: a[] = E/(1-nu^2) b[] = mu c[] = E nu/(1-nu^2) - EPD: a[] = lambda + 2 mu b[] = mu c[] = lambda - 3D: a[] = lambda + 2 mu b[] = mu c[] = lambda - - respectively for the 2D plane strain (EPD), 2D plane stress (EPS) and 3D cases. */ - -Function { - Flag_EPC = 1; - If(Flag_EPC) // Plane stress - a[] = E[]/(1.-nu[]^2); - c[] = E[]*nu[]/(1.-nu[]^2); - Else // Plane strain or 3D - a[] = E[]*(1.-nu[])/(1.+nu[])/(1.-2.*nu[]); - c[] = E[]*nu[]/(1.+nu[])/(1.-2.*nu[]); - EndIf - b[] = E[]/2./(1.+nu[]); - - C_xx[] = Tensor[ a[],0 ,0 , 0 ,b[],0 , 0 ,0 ,b[] ]; - C_xy[] = Tensor[ 0 ,c[],0 , b[],0 ,0 , 0 ,0 ,0 ]; - - C_yx[] = Tensor[ 0 ,b[],0 , c[],0 ,0 , 0 ,0 ,0 ]; - C_yy[] = Tensor[ b[],0 ,0 , 0 ,a[],0 , 0 ,0 ,b[] ]; -} - -/* Clamping boundary condition */ -Constraint { - { Name Displacement_x; - Case { - { Region Sur_Clamp_Mec ; Type Assign ; Value 0; } - } - } - { Name Displacement_y; - Case { - { Region Sur_Clamp_Mec ; Type Assign ; Value 0; } - } - } -} - -/* As explained above, the displacement field is discretized as two scalar - fields "ux" and "uy", which are the spatial components of the vector field - "u" in a fixed Cartesian coordinate system. - - Boundary conditions like - - ux = ... ; - uy = ... ; - - translate naturally into Dirichlet constraints on the scalar "ux" and "uy" - FunctionSpaces. More exotic conditions like - - u . n = ux Cos [th] + uy Sin [th] = ... ; - - are less naturally accounted for within the "grad u" formulation; but they - could be easily implemented with a Lagrange multplier. - - Finite element shape (triangles or quadrangles) makes no difference in the - definition of the FunctionSpaces. The appropriate shape functions to be used - are determined by GetDP at a much lower level on basis of the information - contained in the *.msh file. - - Second order elements, on the other hand, are implemented in the hierarchical - fashion by adding to the first order node-based shape functions a set of - second order edge-based functions to complete a basis for 2d order - polynomials on the reference element. */ - -// Domain of definition of the "ux" and "uy" FunctionSpaces -Group { - Dom_H_u_Mec = Region[ { Vol_Mec, Sur_Force_Mec, Sur_Clamp_Mec} ]; -} - -Flag_Degree = DefineNumber[ 0, Name "Geometry/Use degree 2 (hierarch.)", - Choices{0,1}, Visible 1]; -FE_Order = ( Flag_Degree == 0 ) ? 1 : 2; // Convert flag value into polynomial degree - -FunctionSpace { - { Name H_ux_Mec ; Type Form0 ; - BasisFunction { - { Name sxn ; NameOfCoef uxn ; Function BF_Node ; - Support Dom_H_u_Mec ; Entity NodesOf[ All ] ; } - If ( FE_Order == 2 ) - { Name sxn2 ; NameOfCoef uxn2 ; Function BF_Node_2E ; - Support Dom_H_u_Mec; Entity EdgesOf[ All ] ; } - EndIf - } - Constraint { - { NameOfCoef uxn ; - EntityType NodesOf ; NameOfConstraint Displacement_x ; } - If ( FE_Order == 2 ) - { NameOfCoef uxn2 ; - EntityType EdgesOf ; NameOfConstraint Displacement_x ; } - EndIf - } - } - { Name H_uy_Mec ; Type Form0 ; - BasisFunction { - { Name syn ; NameOfCoef uyn ; Function BF_Node ; - Support Dom_H_u_Mec ; Entity NodesOf[ All ] ; } - If ( FE_Order == 2 ) - { Name syn2 ; NameOfCoef uyn2 ; Function BF_Node_2E ; - Support Dom_H_u_Mec; Entity EdgesOf[ All ] ; } - EndIf - } - Constraint { - { NameOfCoef uyn ; - EntityType NodesOf ; NameOfConstraint Displacement_y ; } - If ( FE_Order == 2 ) - { NameOfCoef uyn2 ; - EntityType EdgesOf ; NameOfConstraint Displacement_y ; } - EndIf - } - } -} - - -Jacobian { - { Name Vol; - Case { - { Region All; Jacobian Vol; } - } - } - { Name Sur; - Case { - { Region All; Jacobian Sur; } - } - } -} - -/* Adapt the number of Gauss points to the polynomial degree of the finite elements - is as simple as this: */ -Integration { - { Name Gauss_v; - Case { - If (FE_Order == 1) - { Type Gauss; - Case { - { GeoElement Line ; NumberOfPoints 3; } - { GeoElement Triangle ; NumberOfPoints 3; } - { GeoElement Quadrangle ; NumberOfPoints 4; } - } - } - Else - { Type Gauss; - Case { - { GeoElement Line ; NumberOfPoints 5; } - { GeoElement Triangle ; NumberOfPoints 7; } - { GeoElement Quadrangle ; NumberOfPoints 7; } - } - } - EndIf - } - } -} - -Formulation { - { Name Elast_u ; Type FemEquation ; - Quantity { - { Name ux ; Type Local ; NameOfSpace H_ux_Mec ; } - { Name uy ; Type Local ; NameOfSpace H_uy_Mec ; } - } - Equation { - Integral { [ -C_xx[] * Dof{d ux}, {d ux} ] ; - In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } - Integral { [ -C_xy[] * Dof{d uy}, {d ux} ] ; - In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } - Integral { [ -C_yx[] * Dof{d ux}, {d uy} ] ; - In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } - Integral { [ -C_yy[] * Dof{d uy}, {d uy} ] ; - In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } - - Integral { [ force_x[] , {ux} ]; - In Vol_Force_Mec ; Jacobian Vol ; Integration Gauss_v ; } - Integral { [ force_y[] , {uy} ]; - In Vol_Force_Mec ; Jacobian Vol ; Integration Gauss_v ; } - - Integral { [ pressure_x[] , {ux} ]; - In Sur_Force_Mec ; Jacobian Sur ; Integration Gauss_v ; } - Integral { [ pressure_y[] , {uy} ]; - In Sur_Force_Mec ; Jacobian Sur ; Integration Gauss_v ; } - } - } -} - -Resolution { - { Name Elast_u ; - System { - { Name Sys_Mec ; NameOfFormulation Elast_u; } - } - Operation { - InitSolution [Sys_Mec]; - Generate[Sys_Mec]; - Solve[Sys_Mec]; - SaveSolution[Sys_Mec] ; - } - } -} - -PostProcessing { - { Name Elast_u ; NameOfFormulation Elast_u ; - PostQuantity { - { Name u ; Value { - Term { [ Vector[ {ux}, {uy}, 0 ]]; In Vol_Mec ; Jacobian Vol ; } - } - } - { Name uy ; Value { - Term { [ 1e3*{uy} ]; In Vol_Mec ; Jacobian Vol ; } - } - } - { Name sig_xx ; Value { - Term { [ CompX[ C_xx[]*{d ux} + C_xy[]*{d uy} ] ]; - In Vol_Mec ; Jacobian Vol ; } - } - } - { Name sig_xy ; Value { - Term { [ CompY[ C_xx[]*{d ux} + C_xy[]*{d uy} ] ]; - In Vol_Mec ; Jacobian Vol ; } - } - } - { Name sig_yy ; Value { - Term { [ CompY [ C_yx[]*{d ux} + C_yy[]*{d uy} ] ]; - In Vol_Mec ; Jacobian Vol ; } - } - } - } - } -} - -PostOperation { - { Name pos; NameOfPostProcessing Elast_u; - Operation { - If(FE_Order == 1) - Print[ sig_xx, OnElementsOf Wrench, File "sigxx.pos" ]; - Print[ u, OnElementsOf Wrench, File "u.pos" ]; - Else - Print[ sig_xx, OnElementsOf Wrench, File "sigxx2.pos" ]; - Print[ u, OnElementsOf Wrench, File "u2.pos" ]; - EndIf - Echo[ StrCat["l=PostProcessing.NbViews-1; ", - "View[l].VectorType = 5; ", - "View[l].ExternalView = l; ", - "View[l].DisplacementFactor = 200; ", - "View[l-1].IntervalsType = 3; " - ], - File "tmp.geo", LastTimeStepOnly] ; - //Print[ sig_yy, OnElementsOf Wrench, File "sigyy.pos" ]; - //Print[ sig_xy, OnElementsOf Wrench, File "sigxy.pos" ]; - Print[ uy, OnPoint{probe_x, probe_y, 0}, - File > "deflection.pos", Format TimeTable, - SendToServer "Solution/Deflection (computed) [mm]", Color "AliceBlue" ]; - } - } -} - -// Tell Gmsh which GetDP commands to execute when running the model. -DefineConstant[ - R_ = {"Elast_u", Name "GetDP/1ResolutionChoices", Visible 0}, - P_ = {"pos", Name "GetDP/2PostOperationChoices", Visible 0}, - C_ = {"-solve -pos -v2", Name "GetDP/9ComputeCommand", Visible 0} -]; +/* ------------------------------------------------------------------- + Tutorial 3 : linear elastic model of a wrench + + Features: + - "grad u" GetDP specific formulation for linear elasticity + - first and second order elements + - triangular and quadrangular elements + + To compute the solution interactively from the Gmsh GUI: + File > Open > wrench.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* Linear elasticity with GetDP: + + GetDP has a peculiar way to deal with linear elasticity. Instead of a vector + field "u = Vector[ ux, uy, uz ]", the displacement field is regarded as two + (2D case) or 3 (3D case) scalar fields. Unlike conventional formulations + then, GetDP's formulation is written in terms of the gradient "grad u" of the + displacement field, which is a non-symmetric tensor, and the needed + symmetrization (to define the strain tensor and relate it to the stress + tensor) is done through the constitutive relationship (Hooke law). The + reason for this unusual formulation is to be able to use also for elastic + problems the powerful geometrical and homological kernel of GetDP, which + relies on the operators grad, curl and div. + + The "grad u" formulation entails a small increase of assembly work but makes + in counterpart lots of geometrical features implemented in GetDP (change of + coordinates, function spaces, etc...) applicable to elastic problems + out-of-the-box, since the scalar fields { ux, uy, uz } have exactly the same + geometrical properties as, e.g. a scalar electric potential or a temperature + field. */ + +Include "wrench2D_common.pro"; + +Young = 1e9 * DefineNumber[ 200, Name "Material/Young modulus [GPa]"]; +Poisson = DefineNumber[ 0.3, Name "Material/Poisson coefficient []"]; +AppliedForce = DefineNumber[ 100, Name "Material/Applied force [N]"]; + +// Approximation of the maximum deflection by an analytical model: +// Deflection = PL^3/(3EI) with I = Width^3*Thickness/12 +Deflection = DefineNumber[4*AppliedForce*((LLength-0.018)/Width)^3/(Young*Thickness)*1e3, + Name "Solution/Deflection (analytical) [mm]", ReadOnly 1]; + +Group { + // Physical regions: Give explicit labels to the regions defined in the .geo file + Wrench = Region[ 1 ]; + Grip = Region[ 2 ]; + Force = Region[ 3 ]; + + // Abstract regions: + Vol_Mec = Region[ Wrench ]; + Vol_Force_Mec = Region[ Wrench ]; + Sur_Clamp_Mec = Region[ Grip ]; + Sur_Force_Mec = Region[ Force ]; + + /* Signification of the abstract regions: + - Vol_Mec : Elastic domain + - Vol_Force_Mec : Region with imposed volumic force + - Sur_Force_Mec : Surface with imposed surface traction + - Sur_Clamp_Mec : Surface with imposed zero displacements (all components) */ +} + +Function { + /* Material coefficients. + No need to define them regionwise here ( E[{Wrench}] = ... ; ) + as there is only one region in this model. */ + E[] = Young; + nu[] = Poisson; + /* Components of the volumic force applied to the region "Vol_Force_Mec" + Gravity could be defined here ( force_y[] = 7000*9.81; ) ; */ + force_x[] = 0; + force_y[] = 0; + /* Components of the surface traction force applied to the region "Sur_Force_Mec" */ + pressure_x[] = 0; + pressure_y[] = -AppliedForce/(SurfaceArea[]*Thickness); // downward vertical force +} + +/* Hooke's law + + The material law + + sigma_ij = C_ijkl epsilon_ij + + is represented in 2D by 4 2x2 tensors C_ij[], i,j=1,2, depending on the Lamé + coefficients of the isotropic linear material, + + lambda = E[]*nu[]/(1.+nu[])/(1.-2.*nu[]) + mu = E[]/2./(1.+nu[]) + + as follows + + EPC: a[] = E/(1-nu^2) b[] = mu c[] = E nu/(1-nu^2) + EPD: a[] = lambda + 2 mu b[] = mu c[] = lambda + 3D: a[] = lambda + 2 mu b[] = mu c[] = lambda + + respectively for the 2D plane strain (EPD), 2D plane stress (EPS) and 3D cases. */ + +Function { + Flag_EPC = 1; + If(Flag_EPC) // Plane stress + a[] = E[]/(1.-nu[]^2); + c[] = E[]*nu[]/(1.-nu[]^2); + Else // Plane strain or 3D + a[] = E[]*(1.-nu[])/(1.+nu[])/(1.-2.*nu[]); + c[] = E[]*nu[]/(1.+nu[])/(1.-2.*nu[]); + EndIf + b[] = E[]/2./(1.+nu[]); + + C_xx[] = Tensor[ a[],0 ,0 , 0 ,b[],0 , 0 ,0 ,b[] ]; + C_xy[] = Tensor[ 0 ,c[],0 , b[],0 ,0 , 0 ,0 ,0 ]; + + C_yx[] = Tensor[ 0 ,b[],0 , c[],0 ,0 , 0 ,0 ,0 ]; + C_yy[] = Tensor[ b[],0 ,0 , 0 ,a[],0 , 0 ,0 ,b[] ]; +} + +/* Clamping boundary condition */ +Constraint { + { Name Displacement_x; + Case { + { Region Sur_Clamp_Mec ; Type Assign ; Value 0; } + } + } + { Name Displacement_y; + Case { + { Region Sur_Clamp_Mec ; Type Assign ; Value 0; } + } + } +} + +/* As explained above, the displacement field is discretized as two scalar + fields "ux" and "uy", which are the spatial components of the vector field + "u" in a fixed Cartesian coordinate system. + + Boundary conditions like + + ux = ... ; + uy = ... ; + + translate naturally into Dirichlet constraints on the scalar "ux" and "uy" + FunctionSpaces. More exotic conditions like + + u . n = ux Cos [th] + uy Sin [th] = ... ; + + are less naturally accounted for within the "grad u" formulation; but they + could be easily implemented with a Lagrange multplier. + + Finite element shape (triangles or quadrangles) makes no difference in the + definition of the FunctionSpaces. The appropriate shape functions to be used + are determined by GetDP at a much lower level on basis of the information + contained in the *.msh file. + + Second order elements, on the other hand, are implemented in the hierarchical + fashion by adding to the first order node-based shape functions a set of + second order edge-based functions to complete a basis for 2d order + polynomials on the reference element. */ + +// Domain of definition of the "ux" and "uy" FunctionSpaces +Group { + Dom_H_u_Mec = Region[ { Vol_Mec, Sur_Force_Mec, Sur_Clamp_Mec} ]; +} + +Flag_Degree = DefineNumber[ 0, Name "Geometry/Use degree 2 (hierarch.)", + Choices{0,1}, Visible 1]; +FE_Order = ( Flag_Degree == 0 ) ? 1 : 2; // Convert flag value into polynomial degree + +FunctionSpace { + { Name H_ux_Mec ; Type Form0 ; + BasisFunction { + { Name sxn ; NameOfCoef uxn ; Function BF_Node ; + Support Dom_H_u_Mec ; Entity NodesOf[ All ] ; } + If ( FE_Order == 2 ) + { Name sxn2 ; NameOfCoef uxn2 ; Function BF_Node_2E ; + Support Dom_H_u_Mec; Entity EdgesOf[ All ] ; } + EndIf + } + Constraint { + { NameOfCoef uxn ; + EntityType NodesOf ; NameOfConstraint Displacement_x ; } + If ( FE_Order == 2 ) + { NameOfCoef uxn2 ; + EntityType EdgesOf ; NameOfConstraint Displacement_x ; } + EndIf + } + } + { Name H_uy_Mec ; Type Form0 ; + BasisFunction { + { Name syn ; NameOfCoef uyn ; Function BF_Node ; + Support Dom_H_u_Mec ; Entity NodesOf[ All ] ; } + If ( FE_Order == 2 ) + { Name syn2 ; NameOfCoef uyn2 ; Function BF_Node_2E ; + Support Dom_H_u_Mec; Entity EdgesOf[ All ] ; } + EndIf + } + Constraint { + { NameOfCoef uyn ; + EntityType NodesOf ; NameOfConstraint Displacement_y ; } + If ( FE_Order == 2 ) + { NameOfCoef uyn2 ; + EntityType EdgesOf ; NameOfConstraint Displacement_y ; } + EndIf + } + } +} + + +Jacobian { + { Name Vol; + Case { + { Region All; Jacobian Vol; } + } + } + { Name Sur; + Case { + { Region All; Jacobian Sur; } + } + } +} + +/* Adapt the number of Gauss points to the polynomial degree of the finite elements + is as simple as this: */ +Integration { + { Name Gauss_v; + Case { + If (FE_Order == 1) + { Type Gauss; + Case { + { GeoElement Line ; NumberOfPoints 3; } + { GeoElement Triangle ; NumberOfPoints 3; } + { GeoElement Quadrangle ; NumberOfPoints 4; } + } + } + Else + { Type Gauss; + Case { + { GeoElement Line ; NumberOfPoints 5; } + { GeoElement Triangle ; NumberOfPoints 7; } + { GeoElement Quadrangle ; NumberOfPoints 7; } + } + } + EndIf + } + } +} + +Formulation { + { Name Elast_u ; Type FemEquation ; + Quantity { + { Name ux ; Type Local ; NameOfSpace H_ux_Mec ; } + { Name uy ; Type Local ; NameOfSpace H_uy_Mec ; } + } + Equation { + Integral { [ -C_xx[] * Dof{d ux}, {d ux} ] ; + In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } + Integral { [ -C_xy[] * Dof{d uy}, {d ux} ] ; + In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } + Integral { [ -C_yx[] * Dof{d ux}, {d uy} ] ; + In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } + Integral { [ -C_yy[] * Dof{d uy}, {d uy} ] ; + In Vol_Mec ; Jacobian Vol ; Integration Gauss_v ; } + + Integral { [ force_x[] , {ux} ]; + In Vol_Force_Mec ; Jacobian Vol ; Integration Gauss_v ; } + Integral { [ force_y[] , {uy} ]; + In Vol_Force_Mec ; Jacobian Vol ; Integration Gauss_v ; } + + Integral { [ pressure_x[] , {ux} ]; + In Sur_Force_Mec ; Jacobian Sur ; Integration Gauss_v ; } + Integral { [ pressure_y[] , {uy} ]; + In Sur_Force_Mec ; Jacobian Sur ; Integration Gauss_v ; } + } + } +} + +Resolution { + { Name Elast_u ; + System { + { Name Sys_Mec ; NameOfFormulation Elast_u; } + } + Operation { + InitSolution [Sys_Mec]; + Generate[Sys_Mec]; + Solve[Sys_Mec]; + SaveSolution[Sys_Mec] ; + } + } +} + +PostProcessing { + { Name Elast_u ; NameOfFormulation Elast_u ; + PostQuantity { + { Name u ; Value { + Term { [ Vector[ {ux}, {uy}, 0 ]]; In Vol_Mec ; Jacobian Vol ; } + } + } + { Name uy ; Value { + Term { [ 1e3*{uy} ]; In Vol_Mec ; Jacobian Vol ; } + } + } + { Name sig_xx ; Value { + Term { [ CompX[ C_xx[]*{d ux} + C_xy[]*{d uy} ] ]; + In Vol_Mec ; Jacobian Vol ; } + } + } + { Name sig_xy ; Value { + Term { [ CompY[ C_xx[]*{d ux} + C_xy[]*{d uy} ] ]; + In Vol_Mec ; Jacobian Vol ; } + } + } + { Name sig_yy ; Value { + Term { [ CompY [ C_yx[]*{d ux} + C_yy[]*{d uy} ] ]; + In Vol_Mec ; Jacobian Vol ; } + } + } + } + } +} + +PostOperation { + { Name pos; NameOfPostProcessing Elast_u; + Operation { + If(FE_Order == 1) + Print[ sig_xx, OnElementsOf Wrench, File "sigxx.pos" ]; + Print[ u, OnElementsOf Wrench, File "u.pos" ]; + Else + Print[ sig_xx, OnElementsOf Wrench, File "sigxx2.pos" ]; + Print[ u, OnElementsOf Wrench, File "u2.pos" ]; + EndIf + Echo[ StrCat["l=PostProcessing.NbViews-1; ", + "View[l].VectorType = 5; ", + "View[l].ExternalView = l; ", + "View[l].DisplacementFactor = 200; ", + "View[l-1].IntervalsType = 3; " + ], + File "tmp.geo", LastTimeStepOnly] ; + //Print[ sig_yy, OnElementsOf Wrench, File "sigyy.pos" ]; + //Print[ sig_xy, OnElementsOf Wrench, File "sigxy.pos" ]; + Print[ uy, OnPoint{probe_x, probe_y, 0}, + File > "deflection.pos", Format TimeTable, + SendToServer "Solution/Deflection (computed) [mm]", Color "AliceBlue" ]; + } + } +} + +// Tell Gmsh which GetDP commands to execute when running the model. +DefineConstant[ + R_ = {"Elast_u", Name "GetDP/1ResolutionChoices", Visible 0}, + P_ = {"pos", Name "GetDP/2PostOperationChoices", Visible 0}, + C_ = {"-solve -pos -v2", Name "GetDP/9ComputeCommand", Visible 0} +]; diff --git a/Elasticity/wrench2D_common.pro b/Elasticity/wrench2D_common.pro index b9b045e..578f64f 100644 --- a/Elasticity/wrench2D_common.pro +++ b/Elasticity/wrench2D_common.pro @@ -1,29 +1,29 @@ -// Some useful conversion coefficients -mm = 1.e-3; // millimeters to meters -cm = 1.e-2; // centimeters to meters -in = 0.0254; // inches to meters -deg = Pi/180.; // degrees to radians - -Refine = - mm*DefineNumber[ 2, Name "Geometry/2Main characteristic length"]; -Recomb = - DefineNumber[ 0, Name "Geometry/1Recombine", Choices{0,1}]; -Thickness = - mm*DefineNumber[ 10, Name "Geometry/4Thickness (mm)"]; -Width = - mm*DefineNumber[ 0.625*in/mm, Name "Geometry/5Arm Width (mm)"]; -LLength = - cm*DefineNumber[ 6.0*in/cm, Name "Geometry/6Arm Length (cm)"]; - -// Definition of the coordinates of the arm end -// at which the maximal deflection will be evaluated. -Inclination = 14*deg; // Arm angle with x-axis -eps = 1e-6; -probe_x = (LLength-eps)*Cos[Inclination]; -probe_y =-(LLength-eps)*Sin[Inclination]; - -// a useful Print command to debug a model or communicate with the user -Printf("Maximal deflection calculated at point (%f,%f)", probe_x, probe_y); - - - +// Some useful conversion coefficients +mm = 1.e-3; // millimeters to meters +cm = 1.e-2; // centimeters to meters +in = 0.0254; // inches to meters +deg = Pi/180.; // degrees to radians + +Refine = + mm*DefineNumber[ 2, Name "Geometry/2Main characteristic length"]; +Recomb = + DefineNumber[ 0, Name "Geometry/1Recombine", Choices{0,1}]; +Thickness = + mm*DefineNumber[ 10, Name "Geometry/4Thickness (mm)"]; +Width = + mm*DefineNumber[ 0.625*in/mm, Name "Geometry/5Arm Width (mm)"]; +LLength = + cm*DefineNumber[ 6.0*in/cm, Name "Geometry/6Arm Length (cm)"]; + +// Definition of the coordinates of the arm end +// at which the maximal deflection will be evaluated. +Inclination = 14*deg; // Arm angle with x-axis +eps = 1e-6; +probe_x = (LLength-eps)*Cos[Inclination]; +probe_y =-(LLength-eps)*Sin[Inclination]; + +// a useful Print command to debug a model or communicate with the user +Printf("Maximal deflection calculated at point (%f,%f)", probe_x, probe_y); + + + diff --git a/Electrostatics/microstrip.geo b/Electrostatics/microstrip.geo index 0d0d855..04ecbf5 100644 --- a/Electrostatics/microstrip.geo +++ b/Electrostatics/microstrip.geo @@ -1,58 +1,58 @@ -/* ------------------------------------------------------------------- - File "microstrip.geo" - - This file is the geometrical description used by Gmsh to produce the mesh - file "microstrip.msh", which is read by GetDP when analysing the file - "microstrip.pro". - ------------------------------------------------------------------- */ - -/* Definition of some parameters for geometrical dimensions, i.e. h (height of - 'Diel1'), w (width of 'Line'), t (thickness of 'Line') xBox (width of the air - box) and yBox (height of the air box) */ - -h = 1.e-3 ; w = 4.72e-3 ; t = 0.035e-3 ; -xBox = w/2. * 6. ; yBox = h * 12. ; - -/* Definition of parameters for local mesh dimensions */ - -s = 1. ; -p0 = h / 10. * s ; -pLine0 = w/2. / 10. * s ; pLine1 = w/2. / 50. * s ; -pxBox = xBox / 10. * s ; pyBox = yBox / 8. * s ; - -/* Definition of gemetrical points */ - -Point(1) = { 0 , 0, 0, p0} ; -Point(2) = { xBox, 0, 0, pxBox} ; -Point(3) = { xBox, h, 0, pxBox} ; -Point(4) = { 0 , h, 0, pLine0} ; -Point(5) = { w/2., h, 0, pLine1} ; -Point(6) = { 0 , h+t, 0, pLine0} ; -Point(7) = { w/2., h+t, 0, pLine1} ; -Point(8) = { 0 , yBox, 0, pyBox} ; -Point(9) = { xBox, yBox, 0, pyBox} ; - -/* Definition of gemetrical lines */ - -Line(1) = {1,2}; Line(2) = {2,3}; Line(3) = {3,9}; -Line(4) = {9,8}; Line(5) = {8,6}; Line(7) = {4,1}; -Line(8) = {5,3}; Line(9) = {4,5}; Line(10) = {6,7}; -Line(11) = {5,7}; - -/* Definition of geometrical surfaces */ - -Curve Loop(12) = {1, 2, -8, -9, 7}; Plane Surface(13) = {12}; -Curve Loop(14) = {10,-11,8,3,4,5}; Plane Surface(15) = {14}; - -/* Definition of Physical entities. The definition of Physical entities - (Surfaces and Curves) tells Gmsh the elements and associated region numbers - that have to be saved in the mesh file 'microstrip.msh'. For example, Region - 111 is made of the triangle elements of the geometric surface 13, whereas - Region 121 is made of line elements of the geometric curves 9, 10 and 11. */ - -Physical Surface("Air", 101) = {15}; -Physical Surface("Dielectric", 111) = {13}; - -Physical Curve("Ground", 120) = {1} ; -Physical Curve("Electrode", 121) = {9,10,11} ; -Physical Curve("Surface infinity", 130) = {2,3,4} ; +/* ------------------------------------------------------------------- + File "microstrip.geo" + + This file is the geometrical description used by Gmsh to produce the mesh + file "microstrip.msh", which is read by GetDP when analysing the file + "microstrip.pro". + ------------------------------------------------------------------- */ + +/* Definition of some parameters for geometrical dimensions, i.e. h (height of + 'Diel1'), w (width of 'Line'), t (thickness of 'Line') xBox (width of the air + box) and yBox (height of the air box) */ + +h = 1.e-3 ; w = 4.72e-3 ; t = 0.035e-3 ; +xBox = w/2. * 6. ; yBox = h * 12. ; + +/* Definition of parameters for local mesh dimensions */ + +s = 1. ; +p0 = h / 10. * s ; +pLine0 = w/2. / 10. * s ; pLine1 = w/2. / 50. * s ; +pxBox = xBox / 10. * s ; pyBox = yBox / 8. * s ; + +/* Definition of gemetrical points */ + +Point(1) = { 0 , 0, 0, p0} ; +Point(2) = { xBox, 0, 0, pxBox} ; +Point(3) = { xBox, h, 0, pxBox} ; +Point(4) = { 0 , h, 0, pLine0} ; +Point(5) = { w/2., h, 0, pLine1} ; +Point(6) = { 0 , h+t, 0, pLine0} ; +Point(7) = { w/2., h+t, 0, pLine1} ; +Point(8) = { 0 , yBox, 0, pyBox} ; +Point(9) = { xBox, yBox, 0, pyBox} ; + +/* Definition of gemetrical lines */ + +Line(1) = {1,2}; Line(2) = {2,3}; Line(3) = {3,9}; +Line(4) = {9,8}; Line(5) = {8,6}; Line(7) = {4,1}; +Line(8) = {5,3}; Line(9) = {4,5}; Line(10) = {6,7}; +Line(11) = {5,7}; + +/* Definition of geometrical surfaces */ + +Curve Loop(12) = {1, 2, -8, -9, 7}; Plane Surface(13) = {12}; +Curve Loop(14) = {10,-11,8,3,4,5}; Plane Surface(15) = {14}; + +/* Definition of Physical entities. The definition of Physical entities + (Surfaces and Curves) tells Gmsh the elements and associated region numbers + that have to be saved in the mesh file 'microstrip.msh'. For example, Region + 111 is made of the triangle elements of the geometric surface 13, whereas + Region 121 is made of line elements of the geometric curves 9, 10 and 11. */ + +Physical Surface("Air", 101) = {15}; +Physical Surface("Dielectric", 111) = {13}; + +Physical Curve("Ground", 120) = {1} ; +Physical Curve("Electrode", 121) = {9,10,11} ; +Physical Curve("Surface infinity", 130) = {2,3,4} ; diff --git a/ElectrostaticsFloating/floating.geo b/ElectrostaticsFloating/floating.geo index e537405..88660c6 100644 --- a/ElectrostaticsFloating/floating.geo +++ b/ElectrostaticsFloating/floating.geo @@ -1,55 +1,55 @@ -/* ------------------------------------------------------------------- - File "floating.geo": copy of "microstrip.geo" from Tutorial 1 - ------------------------------------------------------------------- */ - -/* Definition of some parameters for geometrical dimensions, i.e. h (height of - 'Diel1'), w (width of 'Line'), t (thickness of 'Line') xBox (width of the air - box) and yBox (height of the air box) */ - -h = 1.e-3 ; w = 4.72e-3 ; t = 0.035e-3 ; -xBox = w/2. * 6. ; yBox = h * 12. ; - -/* Definition of parameters for local mesh dimensions */ - -s = 1. ; -p0 = h / 10. * s ; -pLine0 = w/2. / 10. * s ; pLine1 = w/2. / 50. * s ; -pxBox = xBox / 10. * s ; pyBox = yBox / 8. * s ; - -/* Definition of gemetrical points */ - -Point(1) = { 0 , 0, 0, p0} ; -Point(2) = { xBox, 0, 0, pxBox} ; -Point(3) = { xBox, h, 0, pxBox} ; -Point(4) = { 0 , h, 0, pLine0} ; -Point(5) = { w/2., h, 0, pLine1} ; -Point(6) = { 0 , h+t, 0, pLine0} ; -Point(7) = { w/2., h+t, 0, pLine1} ; -Point(8) = { 0 , yBox, 0, pyBox} ; -Point(9) = { xBox, yBox, 0, pyBox} ; - -/* Definition of gemetrical lines */ - -Line(1) = {1,2}; Line(2) = {2,3}; Line(3) = {3,9}; -Line(4) = {9,8}; Line(5) = {8,6}; Line(7) = {4,1}; -Line(8) = {5,3}; Line(9) = {4,5}; Line(10) = {6,7}; -Line(11) = {5,7}; - -/* Definition of geometrical surfaces */ - -Line Loop(12) = {1, 2, -8, -9, 7}; Plane Surface(13) = {12}; -Line Loop(14) = {10,-11,8,3,4,5}; Plane Surface(15) = {14}; - -/* Definition of Physical entities (surfaces, lines). The definition of - Physical entities (Surfaces and Lines) tells Gmsh the elements and associated - region numbers that have to be saved in the mesh file 'microstrip.msh'. For - example, Region 111 is made of the triangle elements of the geometric surface - 13, whereas Region 121 is made of line elements of the geometric lines 9, 10 - and 11. */ - -Physical Surface ("Air", 101) = {15}; -Physical Surface ("Dielectric", 111) = {13}; - -Physical Line ("Ground", 120) = {1} ; -Physical Line ("Electrode", 121) = {9,10,11} ; -Physical Line ("Surface infinity", 130) = {2,3,4} ; +/* ------------------------------------------------------------------- + File "floating.geo": copy of "microstrip.geo" from Tutorial 1 + ------------------------------------------------------------------- */ + +/* Definition of some parameters for geometrical dimensions, i.e. h (height of + 'Diel1'), w (width of 'Line'), t (thickness of 'Line') xBox (width of the air + box) and yBox (height of the air box) */ + +h = 1.e-3 ; w = 4.72e-3 ; t = 0.035e-3 ; +xBox = w/2. * 6. ; yBox = h * 12. ; + +/* Definition of parameters for local mesh dimensions */ + +s = 1. ; +p0 = h / 10. * s ; +pLine0 = w/2. / 10. * s ; pLine1 = w/2. / 50. * s ; +pxBox = xBox / 10. * s ; pyBox = yBox / 8. * s ; + +/* Definition of gemetrical points */ + +Point(1) = { 0 , 0, 0, p0} ; +Point(2) = { xBox, 0, 0, pxBox} ; +Point(3) = { xBox, h, 0, pxBox} ; +Point(4) = { 0 , h, 0, pLine0} ; +Point(5) = { w/2., h, 0, pLine1} ; +Point(6) = { 0 , h+t, 0, pLine0} ; +Point(7) = { w/2., h+t, 0, pLine1} ; +Point(8) = { 0 , yBox, 0, pyBox} ; +Point(9) = { xBox, yBox, 0, pyBox} ; + +/* Definition of gemetrical lines */ + +Line(1) = {1,2}; Line(2) = {2,3}; Line(3) = {3,9}; +Line(4) = {9,8}; Line(5) = {8,6}; Line(7) = {4,1}; +Line(8) = {5,3}; Line(9) = {4,5}; Line(10) = {6,7}; +Line(11) = {5,7}; + +/* Definition of geometrical surfaces */ + +Line Loop(12) = {1, 2, -8, -9, 7}; Plane Surface(13) = {12}; +Line Loop(14) = {10,-11,8,3,4,5}; Plane Surface(15) = {14}; + +/* Definition of Physical entities (surfaces, lines). The definition of + Physical entities (Surfaces and Lines) tells Gmsh the elements and associated + region numbers that have to be saved in the mesh file 'microstrip.msh'. For + example, Region 111 is made of the triangle elements of the geometric surface + 13, whereas Region 121 is made of line elements of the geometric lines 9, 10 + and 11. */ + +Physical Surface ("Air", 101) = {15}; +Physical Surface ("Dielectric", 111) = {13}; + +Physical Line ("Ground", 120) = {1} ; +Physical Line ("Electrode", 121) = {9,10,11} ; +Physical Line ("Surface infinity", 130) = {2,3,4} ; diff --git a/ElectrostaticsFloating/floating.pro b/ElectrostaticsFloating/floating.pro index dbbfe60..50daaa5 100644 --- a/ElectrostaticsFloating/floating.pro +++ b/ElectrostaticsFloating/floating.pro @@ -1,347 +1,347 @@ -/* ------------------------------------------------------------------- - Tutorial 4 : floating potential of a microstrip electrode - - Features: - - Global quantities and their special shape functions - - Computation of the energy dual, i.e. of the armature charge of the electrode - - More on ONELAB parameters (flags, model options, check boxes, menus, ...) - - To compute the solution interactively from the Gmsh GUI: - File > Open > floating.pro - Run (button at the bottom of the left panel) - - ------------------------------------------------------------------- */ - -/* A thing GetDP is pretty good at is the management of global (non-local) basis - functions. Finite element expansions typically associate basis functions to - individual nodes or edges in the mesh. But consider the situation where a - scalar field is set to be uniform over a region of the problem (say a - floating potential electrode in an electrostatic problem). By factorizing the - identical nodal value "v_electrode", a global (non-local) basis function - "BF_electrode" is obtained as factor which is the sum of the shape functions - of all the nodes in the electrode region. This basis function "BF_electrode" - - is a continuous function, scalar in this case, - - is equal to 1 at the nodes of the electrode, and to 0 at all other nodes, - - decreases from 1 to 0 over the one-element-thick layer of elements sharing - at least one node with the electrode region. - - One such glabal basis function can be associated with each electrode in the - system, so that the finite element expansion of the electric scalar potential - reads: - - v = Sum_k sn_k vn_k + Sum_electrode v_electrode BF_electrode - - with the the sum_k running over all nodes except those of the electrode - regions. - - We show in this tutorial how GetDP takes advantage of global quantities and - the associated global basis functions - - to reduce the number of unknowns - - to compute efficiently the electrode charges "Q_electrode", which are - precisely the energy duals of the global "v_electrode" quantities - - to deal with floating potentials, which are the computed electrode - potential when the electrode charge is imposed - - to provide output quantities (charges, armature voltages, capacitances, - ...) that can be immediately used in a external circuit. */ - -Group { - /* Geometrical regions: */ - - Air = Region[101]; - Diel1 = Region[111]; - - Ground = Region[120]; - Microstrip = Region[121]; - SurfInf = Region[130]; - - /* Abstract regions: - - Vol_Ele : volume where -div(epsilon grad v) = 0 is solved - Sur_Neu_Ele : surface where non homogeneous Neumann boundary conditions - (on n.d = -n . (epsilon grad v)) are imposed - Sur_Electrodes_Ele : electrode regions */ - - Vol_Ele = Region[ {Air, Diel1} ]; - Sur_Neu_Ele = Region[ {} ]; - Sur_Electrodes_Ele = Region [ {Ground, Microstrip} ]; -} - -/* A number of ONELAB parameters are defined to define model parameters or model - options interactively. */ - -MicrostripTypeBC = DefineNumber[0, Name "1Microstrip excitation/Type", - Choices{0="Fixed voltage", 1="Fixed charge"}] ; -MicrostripValueBC = DefineNumber[1e-3, Name "1Microstrip excitation/Value"] ; -EpsilonRelDiel = DefineNumber[9.8, Name "2Dielectric/Relative permittivity"] ; -DisplayGlobalBF = DefineNumber[0, Name "3Options/Display global basis functions", - Choices {0,1} ] ; -OverwriteOutput = DefineNumber[1, Name "3Options/Overwrite output.txt file", - Choices {0,1} ] ; - -Function { - eps0 = 8.854187818e-12; // permittivity of empty space - epsilon[Air] = eps0; - epsilon[Diel1] = EpsilonRelDiel * eps0; -} - -Constraint { - /* The Dirichlet boundary condition on the local electric potential is no - longer used. The microstrip and the ground are now treated as electrodes, - whose voltage is imposed with the "SetGlobalPotential" constraint below. */ - { Name Dirichlet_Ele; Type Assign; - Case { - } - } - - { Name SetGlobalPotential; Type Assign; - Case { - /* Define the imposed potential regionwise on the different parts of - "Sur_Electrodes_Ele". No voltage is imposed to the Microstrip electrode - when the "Fixed charge" option is enabled (if MicrostripTypeBC != 0). */ - { Region Ground; Value 0; } - If(!MicrostripTypeBC) - { Region Microstrip; Value MicrostripValueBC; } - EndIf - } - } - { Name SetArmatureCharge; Type Assign; - Case { - /* Impose the charge if MicrostripTypeBC != 0 */ - If(MicrostripTypeBC) - { Region Microstrip; Value MicrostripValueBC; } - EndIf - } - } -} - -Group{ - /* The domain of definition lists all regions on which the field "v" is - defined.*/ - Dom_Hgrad_v_Ele = Region[ {Vol_Ele, Sur_Neu_Ele, Sur_Electrodes_Ele} ]; -} - -FunctionSpace { - /* The magic in the treatment of global quantitities by GetDP is in the fact - that nearly all the work is done at the level of the FunctionSpace - definition. The finite element expansion of "v" is - - v = Sum_k sn_k vn_k + Sum_electrode v_electrode BF_electrode - - with the the sum_k running over all nodes except those of the electrode - regions. This is exactly what one finds in the FunctionSpace definition - below with "sf" standing for "BF_electrode" and "vf" for "v_electrode". - - The global quantities are attributed an explicit and meaningful name in the - "GlobalQuantity" section; these names are used in the corresponding - "GlobalTerm" in the Formulation. Such global terms are the equivalent of a - "Integral" term, but where no integration needs to be performed. The - "AssociatedWith" statement manifests the fact that the global potential of - an electrode is the (electrostatic) energy dual of the electric charge - carried by that electrode. Indeed, let us consider the electrostatic weak - formulation derived in Tutorial 1: find v in Hgradv_Ele such that - - (epsilon grad v, grad v')_Vol_Ele + (n . (epsilon grad v), v')_Bnd_Vol_Ele = 0 - - holds for all test functions v'. When the test-function v' is BF_electrode, - the boundary term reduces to - - (n . (epsilon grad v), BF_electrode)_Sur_Electrodes_Ele. - - Since BF_electrode == 1 on the electrode, the boundary term is actually - simply equal to the integral of (n . epsilon grad v) on the electrode, - i.e. the flux of the displacement field, which is by definition the - charge Q_electrode carried by the electrodes. - - By checking the "Display global basis functions" checkbox and running the - model, you can take a look on how the two "BF_electrode" basis functions in - this model look like. Constraints can then be set on either component of - the FunctionSpace. Besides the usual Dirichlet boundary condition on the - local field, which is left here for the sake of completeness but is not - used in this model, there is the possibility to fix either the - GlobalPotential or the ArmatureCharge of each indidual electrode (not both, - of course). When the ArmatureCharge is fixed, the computed GlobalPotential - computed for that electrode is the so-called floating potential. */ - - { Name Hgrad_v_Ele; Type Form0; - BasisFunction { - { Name sn; NameOfCoef vn; Function BF_Node; - Support Dom_Hgrad_v_Ele; Entity NodesOf[ All, Not Sur_Electrodes_Ele ]; } - { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; - Support Dom_Hgrad_v_Ele; Entity GroupsOfNodesOf[ Sur_Electrodes_Ele ]; } - } - GlobalQuantity { - { Name GlobalPotential; Type AliasOf ; NameOfCoef vf; } - { Name ArmatureCharge ; Type AssociatedWith; NameOfCoef vf; } - } - Constraint { - { NameOfCoef vn; EntityType NodesOf; - NameOfConstraint Dirichlet_Ele; } // unused in this model, left for completeness - { NameOfCoef GlobalPotential; EntityType GroupsOfNodesOf; - NameOfConstraint SetGlobalPotential; } - { NameOfCoef ArmatureCharge; EntityType GroupsOfNodesOf; - NameOfConstraint SetArmatureCharge; } - } - // Subspace definition only needed to display BF_electrode in PostProcessing - SubSpace { - { Name vf; NameOfBasisFunction sf; } - } - } -} - -Jacobian { - { Name Vol ; - Case { - { Region All ; Jacobian Vol ; } - } - } -} - -Integration { - { Name Int ; - Case { {Type Gauss ; - Case { { GeoElement Triangle ; NumberOfPoints 4 ; } - { GeoElement Quadrangle ; NumberOfPoints 4 ; } } - } - } - } -} - -Formulation { - /* The formulation only contains minor changes compared to formulation from - the first tutorial. The global quantities are declared as "Global" in the - "Quantity" section, and a "GlobalTerm" is added that triggers the assembly - of the additional equation per electrode (the "pre-integrated" boundary - term) in the system to compute the charge Q_electrode, which - satisfies (just consider the equation corresponding to the test function - BF_electrode): - - Q_electrode = (-epsilon grad v, grad BF_electrode)_Vol_Ele */ - { Name Electrostatics_v; Type FemEquation; - Quantity { - { Name v; Type Local; NameOfSpace Hgrad_v_Ele; } - { Name U; Type Global; NameOfSpace Hgrad_v_Ele [GlobalPotential]; } - { Name Q; Type Global; NameOfSpace Hgrad_v_Ele [ArmatureCharge]; } - // next line only needed to display the BF_electrode in PostProcessing - { Name vf; Type Local; NameOfSpace Hgrad_v_Ele [vf]; } - } - Equation { - Integral { [ epsilon[] * Dof{d v} , {d v} ]; - In Vol_Ele; Jacobian Vol; Integration Int; } - GlobalTerm { [ -Dof{Q} , {U} ]; In Sur_Electrodes_Ele; } - } - } -} - -Resolution { - { Name EleSta_v; - System { - { Name Sys_Ele; NameOfFormulation Electrostatics_v; } - } - Operation { - Generate[Sys_Ele]; Solve[Sys_Ele]; SaveSolution[Sys_Ele]; - } - } -} - -PostProcessing { - { Name EleSta_v; NameOfFormulation Electrostatics_v; - Quantity { - { Name v; Value { - Term { [ {v} ]; In Vol_Ele; Jacobian Vol; } - } - } - { Name e; Value { - Term { [ -{d v} ]; In Vol_Ele; Jacobian Vol; } - } - } - { Name d; Value { - Term { [ -epsilon[] * {d v} ]; In Vol_Ele; Jacobian Vol; } - } - } - { Name Q; Value { - Term { [ {Q} ]; In Sur_Electrodes_Ele; } - } - } - { Name U; Value { - Term { [ {U} ]; In Sur_Electrodes_Ele; } - } - } - { Name C; Value { - Term { [ {Q}/{U} ]; In Sur_Electrodes_Ele; } - } - } - { Name energy; Value { - Integral { Type Global; // global integral over Vol_Ele - [ epsilon[] / 2. * SquNorm[{d v}] ]; - In Vol_Ele; Jacobian Vol; Integration Int; - } - } - } - // next lines only needed to display global BF in PostProcessing - { Name BFGround; Value { - Term { [ BF{vf} ]; In Dom_Hgrad_v_Ele; SubRegion Ground; Jacobian Vol; } - } - } - { Name BFMicrostrip; Value { - Term { [ BF{vf} ]; In Dom_Hgrad_v_Ele; SubRegion Microstrip; Jacobian Vol; } - } - } - } - } -} - -/* Various output results are generated, which are both displayed in the - graphical user interface, and stored in disk files. In particular, global - quantities related results are stored in the "output.txt" file. A user option - allows to chose to not overwrite the "output.txt" file when running a new - simulation. */ - -PostOperation { - { Name Map; NameOfPostProcessing EleSta_v; - Operation { - If( DisplayGlobalBF ) - Print[ BFGround, OnElementsOf Dom_Hgrad_v_Ele, File "BFGround.pos" ]; - Echo[ StrCat["l=PostProcessing.NbViews-1;", - "View[l].IntervalsType = 1;", - "View[l].NbIso = 40;", - "View[l].ShowElement = 1;"], - File "BFGround.opt", LastTimeStepOnly] ; - - Print[ BFMicrostrip, OnElementsOf Dom_Hgrad_v_Ele, - File "BFMicrostrip.pos" ]; - Echo[ StrCat["l=PostProcessing.NbViews-1;", - "View[l].IntervalsType = 1;", - "View[l].NbIso = 40;", - "View[l].ShowElement = 1;"], - File "BFMicrostrip.opt", LastTimeStepOnly] ; - EndIf - - Print[ v, OnElementsOf Dom_Hgrad_v_Ele, File "v.pos" ]; - Echo[ StrCat["l=PostProcessing.NbViews-1;", - "View[l].IntervalsType = 3;", - "View[l].NbIso = 40;"], - File "v.opt", LastTimeStepOnly] ; - - If(OverwriteOutput) - DeleteFile[ "output.txt" ]; - EndIf - - Echo[ "Microstrip charge [C]:", Format Table, File > "output.txt"] ; - Print[ Q, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", - Format Table, SendToServer "Output/Microstrip/Charge [C]" ]; - Echo[ "Microstrip potential [V]:", Format Table, File > "output.txt"] ; - Print[ U, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", - Format Table, SendToServer "Output/Microstrip/Potential [V]" ]; - Echo[ "Ground charge [C]:", Format Table, File > "output.txt"] ; - Print[ Q, OnRegion Ground, File > "output.txt", Color "AliceBlue", - Format Table, SendToServer "Output/Ground/Charge [C]" ]; - Echo[ "Microstrip capacitance [F]:", Format Table, File > "output.txt"] ; - Print[ C, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", - Format Table, SendToServer "Output/Global/Capacitance [F]" ]; - Echo[ "Electrostatic energy [J]:", Format Table, File > "output.txt"] ; - Print[ energy, OnGlobal, File > "output.txt", - Color "AliceBlue", - Format Table, SendToServer "Output/Global/Energy [J]" ]; - } - } -} +/* ------------------------------------------------------------------- + Tutorial 4 : floating potential of a microstrip electrode + + Features: + - Global quantities and their special shape functions + - Computation of the energy dual, i.e. of the armature charge of the electrode + - More on ONELAB parameters (flags, model options, check boxes, menus, ...) + + To compute the solution interactively from the Gmsh GUI: + File > Open > floating.pro + Run (button at the bottom of the left panel) + + ------------------------------------------------------------------- */ + +/* A thing GetDP is pretty good at is the management of global (non-local) basis + functions. Finite element expansions typically associate basis functions to + individual nodes or edges in the mesh. But consider the situation where a + scalar field is set to be uniform over a region of the problem (say a + floating potential electrode in an electrostatic problem). By factorizing the + identical nodal value "v_electrode", a global (non-local) basis function + "BF_electrode" is obtained as factor which is the sum of the shape functions + of all the nodes in the electrode region. This basis function "BF_electrode" + - is a continuous function, scalar in this case, + - is equal to 1 at the nodes of the electrode, and to 0 at all other nodes, + - decreases from 1 to 0 over the one-element-thick layer of elements sharing + at least one node with the electrode region. + + One such glabal basis function can be associated with each electrode in the + system, so that the finite element expansion of the electric scalar potential + reads: + + v = Sum_k sn_k vn_k + Sum_electrode v_electrode BF_electrode + + with the the sum_k running over all nodes except those of the electrode + regions. + + We show in this tutorial how GetDP takes advantage of global quantities and + the associated global basis functions + - to reduce the number of unknowns + - to compute efficiently the electrode charges "Q_electrode", which are + precisely the energy duals of the global "v_electrode" quantities + - to deal with floating potentials, which are the computed electrode + potential when the electrode charge is imposed + - to provide output quantities (charges, armature voltages, capacitances, + ...) that can be immediately used in a external circuit. */ + +Group { + /* Geometrical regions: */ + + Air = Region[101]; + Diel1 = Region[111]; + + Ground = Region[120]; + Microstrip = Region[121]; + SurfInf = Region[130]; + + /* Abstract regions: + + Vol_Ele : volume where -div(epsilon grad v) = 0 is solved + Sur_Neu_Ele : surface where non homogeneous Neumann boundary conditions + (on n.d = -n . (epsilon grad v)) are imposed + Sur_Electrodes_Ele : electrode regions */ + + Vol_Ele = Region[ {Air, Diel1} ]; + Sur_Neu_Ele = Region[ {} ]; + Sur_Electrodes_Ele = Region [ {Ground, Microstrip} ]; +} + +/* A number of ONELAB parameters are defined to define model parameters or model + options interactively. */ + +MicrostripTypeBC = DefineNumber[0, Name "1Microstrip excitation/Type", + Choices{0="Fixed voltage", 1="Fixed charge"}] ; +MicrostripValueBC = DefineNumber[1e-3, Name "1Microstrip excitation/Value"] ; +EpsilonRelDiel = DefineNumber[9.8, Name "2Dielectric/Relative permittivity"] ; +DisplayGlobalBF = DefineNumber[0, Name "3Options/Display global basis functions", + Choices {0,1} ] ; +OverwriteOutput = DefineNumber[1, Name "3Options/Overwrite output.txt file", + Choices {0,1} ] ; + +Function { + eps0 = 8.854187818e-12; // permittivity of empty space + epsilon[Air] = eps0; + epsilon[Diel1] = EpsilonRelDiel * eps0; +} + +Constraint { + /* The Dirichlet boundary condition on the local electric potential is no + longer used. The microstrip and the ground are now treated as electrodes, + whose voltage is imposed with the "SetGlobalPotential" constraint below. */ + { Name Dirichlet_Ele; Type Assign; + Case { + } + } + + { Name SetGlobalPotential; Type Assign; + Case { + /* Define the imposed potential regionwise on the different parts of + "Sur_Electrodes_Ele". No voltage is imposed to the Microstrip electrode + when the "Fixed charge" option is enabled (if MicrostripTypeBC != 0). */ + { Region Ground; Value 0; } + If(!MicrostripTypeBC) + { Region Microstrip; Value MicrostripValueBC; } + EndIf + } + } + { Name SetArmatureCharge; Type Assign; + Case { + /* Impose the charge if MicrostripTypeBC != 0 */ + If(MicrostripTypeBC) + { Region Microstrip; Value MicrostripValueBC; } + EndIf + } + } +} + +Group{ + /* The domain of definition lists all regions on which the field "v" is + defined.*/ + Dom_Hgrad_v_Ele = Region[ {Vol_Ele, Sur_Neu_Ele, Sur_Electrodes_Ele} ]; +} + +FunctionSpace { + /* The magic in the treatment of global quantitities by GetDP is in the fact + that nearly all the work is done at the level of the FunctionSpace + definition. The finite element expansion of "v" is + + v = Sum_k sn_k vn_k + Sum_electrode v_electrode BF_electrode + + with the the sum_k running over all nodes except those of the electrode + regions. This is exactly what one finds in the FunctionSpace definition + below with "sf" standing for "BF_electrode" and "vf" for "v_electrode". + + The global quantities are attributed an explicit and meaningful name in the + "GlobalQuantity" section; these names are used in the corresponding + "GlobalTerm" in the Formulation. Such global terms are the equivalent of a + "Integral" term, but where no integration needs to be performed. The + "AssociatedWith" statement manifests the fact that the global potential of + an electrode is the (electrostatic) energy dual of the electric charge + carried by that electrode. Indeed, let us consider the electrostatic weak + formulation derived in Tutorial 1: find v in Hgradv_Ele such that + + (epsilon grad v, grad v')_Vol_Ele + (n . (epsilon grad v), v')_Bnd_Vol_Ele = 0 + + holds for all test functions v'. When the test-function v' is BF_electrode, + the boundary term reduces to + + (n . (epsilon grad v), BF_electrode)_Sur_Electrodes_Ele. + + Since BF_electrode == 1 on the electrode, the boundary term is actually + simply equal to the integral of (n . epsilon grad v) on the electrode, + i.e. the flux of the displacement field, which is by definition the + charge Q_electrode carried by the electrodes. + + By checking the "Display global basis functions" checkbox and running the + model, you can take a look on how the two "BF_electrode" basis functions in + this model look like. Constraints can then be set on either component of + the FunctionSpace. Besides the usual Dirichlet boundary condition on the + local field, which is left here for the sake of completeness but is not + used in this model, there is the possibility to fix either the + GlobalPotential or the ArmatureCharge of each indidual electrode (not both, + of course). When the ArmatureCharge is fixed, the computed GlobalPotential + computed for that electrode is the so-called floating potential. */ + + { Name Hgrad_v_Ele; Type Form0; + BasisFunction { + { Name sn; NameOfCoef vn; Function BF_Node; + Support Dom_Hgrad_v_Ele; Entity NodesOf[ All, Not Sur_Electrodes_Ele ]; } + { Name sf; NameOfCoef vf; Function BF_GroupOfNodes; + Support Dom_Hgrad_v_Ele; Entity GroupsOfNodesOf[ Sur_Electrodes_Ele ]; } + } + GlobalQuantity { + { Name GlobalPotential; Type AliasOf ; NameOfCoef vf; } + { Name ArmatureCharge ; Type AssociatedWith; NameOfCoef vf; } + } + Constraint { + { NameOfCoef vn; EntityType NodesOf; + NameOfConstraint Dirichlet_Ele; } // unused in this model, left for completeness + { NameOfCoef GlobalPotential; EntityType GroupsOfNodesOf; + NameOfConstraint SetGlobalPotential; } + { NameOfCoef ArmatureCharge; EntityType GroupsOfNodesOf; + NameOfConstraint SetArmatureCharge; } + } + // Subspace definition only needed to display BF_electrode in PostProcessing + SubSpace { + { Name vf; NameOfBasisFunction sf; } + } + } +} + +Jacobian { + { Name Vol ; + Case { + { Region All ; Jacobian Vol ; } + } + } +} + +Integration { + { Name Int ; + Case { {Type Gauss ; + Case { { GeoElement Triangle ; NumberOfPoints 4 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } } + } + } + } +} + +Formulation { + /* The formulation only contains minor changes compared to formulation from + the first tutorial. The global quantities are declared as "Global" in the + "Quantity" section, and a "GlobalTerm" is added that triggers the assembly + of the additional equation per electrode (the "pre-integrated" boundary + term) in the system to compute the charge Q_electrode, which + satisfies (just consider the equation corresponding to the test function + BF_electrode): + + Q_electrode = (-epsilon grad v, grad BF_electrode)_Vol_Ele */ + { Name Electrostatics_v; Type FemEquation; + Quantity { + { Name v; Type Local; NameOfSpace Hgrad_v_Ele; } + { Name U; Type Global; NameOfSpace Hgrad_v_Ele [GlobalPotential]; } + { Name Q; Type Global; NameOfSpace Hgrad_v_Ele [ArmatureCharge]; } + // next line only needed to display the BF_electrode in PostProcessing + { Name vf; Type Local; NameOfSpace Hgrad_v_Ele [vf]; } + } + Equation { + Integral { [ epsilon[] * Dof{d v} , {d v} ]; + In Vol_Ele; Jacobian Vol; Integration Int; } + GlobalTerm { [ -Dof{Q} , {U} ]; In Sur_Electrodes_Ele; } + } + } +} + +Resolution { + { Name EleSta_v; + System { + { Name Sys_Ele; NameOfFormulation Electrostatics_v; } + } + Operation { + Generate[Sys_Ele]; Solve[Sys_Ele]; SaveSolution[Sys_Ele]; + } + } +} + +PostProcessing { + { Name EleSta_v; NameOfFormulation Electrostatics_v; + Quantity { + { Name v; Value { + Term { [ {v} ]; In Vol_Ele; Jacobian Vol; } + } + } + { Name e; Value { + Term { [ -{d v} ]; In Vol_Ele; Jacobian Vol; } + } + } + { Name d; Value { + Term { [ -epsilon[] * {d v} ]; In Vol_Ele; Jacobian Vol; } + } + } + { Name Q; Value { + Term { [ {Q} ]; In Sur_Electrodes_Ele; } + } + } + { Name U; Value { + Term { [ {U} ]; In Sur_Electrodes_Ele; } + } + } + { Name C; Value { + Term { [ {Q}/{U} ]; In Sur_Electrodes_Ele; } + } + } + { Name energy; Value { + Integral { Type Global; // global integral over Vol_Ele + [ epsilon[] / 2. * SquNorm[{d v}] ]; + In Vol_Ele; Jacobian Vol; Integration Int; + } + } + } + // next lines only needed to display global BF in PostProcessing + { Name BFGround; Value { + Term { [ BF{vf} ]; In Dom_Hgrad_v_Ele; SubRegion Ground; Jacobian Vol; } + } + } + { Name BFMicrostrip; Value { + Term { [ BF{vf} ]; In Dom_Hgrad_v_Ele; SubRegion Microstrip; Jacobian Vol; } + } + } + } + } +} + +/* Various output results are generated, which are both displayed in the + graphical user interface, and stored in disk files. In particular, global + quantities related results are stored in the "output.txt" file. A user option + allows to chose to not overwrite the "output.txt" file when running a new + simulation. */ + +PostOperation { + { Name Map; NameOfPostProcessing EleSta_v; + Operation { + If( DisplayGlobalBF ) + Print[ BFGround, OnElementsOf Dom_Hgrad_v_Ele, File "BFGround.pos" ]; + Echo[ StrCat["l=PostProcessing.NbViews-1;", + "View[l].IntervalsType = 1;", + "View[l].NbIso = 40;", + "View[l].ShowElement = 1;"], + File "BFGround.opt", LastTimeStepOnly] ; + + Print[ BFMicrostrip, OnElementsOf Dom_Hgrad_v_Ele, + File "BFMicrostrip.pos" ]; + Echo[ StrCat["l=PostProcessing.NbViews-1;", + "View[l].IntervalsType = 1;", + "View[l].NbIso = 40;", + "View[l].ShowElement = 1;"], + File "BFMicrostrip.opt", LastTimeStepOnly] ; + EndIf + + Print[ v, OnElementsOf Dom_Hgrad_v_Ele, File "v.pos" ]; + Echo[ StrCat["l=PostProcessing.NbViews-1;", + "View[l].IntervalsType = 3;", + "View[l].NbIso = 40;"], + File "v.opt", LastTimeStepOnly] ; + + If(OverwriteOutput) + DeleteFile[ "output.txt" ]; + EndIf + + Echo[ "Microstrip charge [C]:", Format Table, File > "output.txt"] ; + Print[ Q, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", + Format Table, SendToServer "Output/Microstrip/Charge [C]" ]; + Echo[ "Microstrip potential [V]:", Format Table, File > "output.txt"] ; + Print[ U, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", + Format Table, SendToServer "Output/Microstrip/Potential [V]" ]; + Echo[ "Ground charge [C]:", Format Table, File > "output.txt"] ; + Print[ Q, OnRegion Ground, File > "output.txt", Color "AliceBlue", + Format Table, SendToServer "Output/Ground/Charge [C]" ]; + Echo[ "Microstrip capacitance [F]:", Format Table, File > "output.txt"] ; + Print[ C, OnRegion Microstrip, File > "output.txt", Color "AliceBlue", + Format Table, SendToServer "Output/Global/Capacitance [F]" ]; + Echo[ "Electrostatic energy [J]:", Format Table, File > "output.txt"] ; + Print[ energy, OnGlobal, File > "output.txt", + Color "AliceBlue", + Format Table, SendToServer "Output/Global/Energy [J]" ]; + } + } +} diff --git a/Magnetodynamics/Lib_MagStaDyn_av_2D_Cir.pro b/Magnetodynamics/Lib_MagStaDyn_av_2D_Cir.pro index 0ec6524..cf925ed 100644 --- a/Magnetodynamics/Lib_MagStaDyn_av_2D_Cir.pro +++ b/Magnetodynamics/Lib_MagStaDyn_av_2D_Cir.pro @@ -1,478 +1,478 @@ -// This is a template .pro file containing a general formulation for 2D -// magnetostatic and magnetodynamic problems in terms of the magnetic vector -// potential a (potentially coupled with the electric scalar potential v), with -// optional circuit coupling. - -// Below are definitions of the constants (inside "DefineConstant"), groups -// (inside "DefineGroup") and functions (inside "DefineFunction") that can be -// redefined from outside this template. - -DefineConstant[ - Flag_FrequencyDomain = 1, // frequency-domain or time-domain simulation - Flag_CircuitCoupling = 0 // consider coupling with external electric circuit - CoefPower = 0.5, // coefficient for power calculations - Freq = 50, // frequency (for harmonic simulations) - TimeInit = 0, // intial time (for time-domain simulations) - TimeFinal = 1/50, // final time (for time-domain simulations) - DeltaTime = 1/500, // time step (for time-domain simulations) - FE_Order = 1 // finite element order - Val_Rint = 0, // interior radius of annulus shell transformation region (Vol_Inf_Mag) - Val_Rext = 0 // exterior radius of annulus shell transformation region (Vol_Inf_Mag) -]; - -Group { - DefineGroup[ - Vol_CC_Mag, // the non-conducting part - Vol_C_Mag, // the conducting part - Vol_V_Mag, // a moving conducting part, with invariant mesh - Vol_M_Mag, // permanent magnets - Vol_S0_Mag, // current source domain with imposed current densities js0 - Vol_S_Mag, // current source domain with imposed current, imposed voltage or - // circuit coupling - Vol_Inf_Mag, // annulus where a infinite shell transformation is applied - Sur_FluxTube_Mag, // boundary with Neumann BC - Sur_Perfect_Mag, // boundary of perfect conductors (i.e. non-meshed) - Sur_Imped_Mag // boundary of conductors approximated by a surface impedance - // (i.e. non-meshed) - ]; - If(Flag_CircuitCoupling) - DefineGroup[ - SourceV_Cir, // voltage sources - SourceI_Cir, // current sources - Resistance_Cir, // resistors (linear) - Inductance_Cir, // inductors - Capacitance_Cir, // capacitors - Diode_Cir // diodes (treated as nonlinear resistors) - ]; - EndIf -} - -Function { - DefineFunction[ - nu, // reluctivity (in Vol_Mag) - sigma, // conductivity (in Vol_C_Mag and Vol_S_Mag) - br, // remanent magnetic flux density (in Vol_M_Mag) - js0, // source current density (in Vol_S0_Mag) - nxh, // n x magnetic field (on Sur_FluxTube_Mag) - Velocity, // velocity of moving part Vol_V_Mag - Ns, // number of turns (in Vol_S_Mag) - Sc, // cross-section of windings (in Vol_S_Mag) - CoefGeos, // geometrical coefficient for 2D or 2D axi model - Ysur // surface admittance (inverse of surface impedance Zsur) on Sur_Imped_Mag - ]; - If(Flag_CircuitCoupling) - DefineFunction[ - Resistance, // resistance values - Inductance, // inductance values - Capacitance // capacitance values - ]; - EndIf -} - -// End of definitions. - -Group{ - // all volumes - Vol_Mag = Region[ {Vol_CC_Mag, Vol_C_Mag, Vol_V_Mag, Vol_M_Mag, Vol_S0_Mag, Vol_S_Mag} ]; - // all volumes + surfaces on which integrals will be computed - Dom_Mag = Region[ {Vol_Mag, Sur_FluxTube_Mag, Sur_Perfect_Mag, Sur_Imped_Mag} ]; - If(Flag_CircuitCoupling) - // all circuit impedances - DomainZ_Cir = Region[ {Resistance_Cir, Inductance_Cir, Capacitance_Cir} ]; - // all circuit sources - DomainSource_Cir = Region[ {SourceV_Cir, SourceI_Cir} ]; - // all circuit elements - Domain_Cir = Region[ {DomainZ_Cir, DomainSource_Cir} ]; - EndIf -} - -Jacobian { - { Name Vol; - Case { - { Region Vol_Inf_Mag ; - Jacobian VolSphShell {Val_Rint, Val_Rext} ; } - { Region All; Jacobian Vol; } - } - } - { Name Sur; - Case { - { Region All; Jacobian Sur; } - } - } -} - -Integration { - { Name Gauss_v; - Case { - { Type Gauss; - Case { - { GeoElement Point; NumberOfPoints 1; } - { GeoElement Line; NumberOfPoints 5; } - { GeoElement Triangle; NumberOfPoints 7; } - { GeoElement Quadrangle; NumberOfPoints 4; } - { GeoElement Tetrahedron; NumberOfPoints 15; } - { GeoElement Hexahedron; NumberOfPoints 14; } - { GeoElement Prism; NumberOfPoints 21; } - } - } - } - } -} - -// Same FunctionSpace for both static and dynamic formulations -FunctionSpace { - { Name Hcurl_a_2D; Type Form1P; // 1-form (circulations) on edges - // perpendicular to the plane of study - BasisFunction { - // \vec{a}(x) = \sum_{n \in N(Domain)} a_n \vec{s}_n(x) - // without nodes on perfect conductors (where a is constant) - { Name s_n; NameOfCoef a_n; Function BF_PerpendicularEdge; - Support Dom_Mag; Entity NodesOf[All, Not Sur_Perfect_Mag]; } - - // global basis function on boundary of perfect conductors - { Name s_skin; NameOfCoef a_skin; Function BF_GroupOfPerpendicularEdges; - Support Dom_Mag; Entity GroupsOfNodesOf[Sur_Perfect_Mag]; } - - // additional basis functions for 2nd order interpolation - If(FE_Order == 2) - { Name s_e; NameOfCoef a_e; Function BF_PerpendicularEdge_2E; - Support Vol_Mag; Entity EdgesOf[All]; } - EndIf - } - GlobalQuantity { - { Name A; Type AliasOf; NameOfCoef a_skin; } - { Name I; Type AssociatedWith; NameOfCoef a_skin; } - } - Constraint { - { NameOfCoef a_n; - EntityType NodesOf; NameOfConstraint MagneticVectorPotential_2D; } - - { NameOfCoef I; - EntityType GroupsOfNodesOf; NameOfConstraint Current_2D; } - - If(FE_Order == 2) - { NameOfCoef a_e; - EntityType EdgesOf; NameOfConstraint MagneticVectorPotential_2D_0; } - EndIf - } - } -} - -FunctionSpace { - // Gradient of Electric scalar potential (2D) - { Name Hregion_u_2D; Type Form1P; // same as for \vec{a} - BasisFunction { - { Name sr; NameOfCoef ur; Function BF_RegionZ; - // constant vector (over the region) with nonzero z-component only - Support Region[{Vol_C_Mag, Sur_Imped_Mag}]; - Entity Region[{Vol_C_Mag, Sur_Imped_Mag}]; } - } - GlobalQuantity { - { Name U; Type AliasOf; NameOfCoef ur; } - { Name I; Type AssociatedWith; NameOfCoef ur; } - } - Constraint { - { NameOfCoef U; - EntityType Region; NameOfConstraint Voltage_2D; } - { NameOfCoef I; - EntityType Region; NameOfConstraint Current_2D; } - } - } - - // Current in stranded coil (2D) - { Name Hregion_i_2D; Type Vector; - BasisFunction { - { Name sr; NameOfCoef ir; Function BF_RegionZ; - Support Vol_S_Mag; Entity Vol_S_Mag; } - } - GlobalQuantity { - { Name Is; Type AliasOf; NameOfCoef ir; } - { Name Us; Type AssociatedWith; NameOfCoef ir; } - } - Constraint { - { NameOfCoef Us; - EntityType Region; NameOfConstraint Voltage_2D; } - { NameOfCoef Is; - EntityType Region; NameOfConstraint Current_2D; } - } - } -} - -If(Flag_CircuitCoupling) - // UZ and IZ for impedances - FunctionSpace { - { Name Hregion_Z; Type Scalar; - BasisFunction { - { Name sr; NameOfCoef ir; Function BF_Region; - Support Domain_Cir; Entity Domain_Cir; } - } - GlobalQuantity { - { Name Iz; Type AliasOf; NameOfCoef ir; } - { Name Uz; Type AssociatedWith; NameOfCoef ir; } - } - Constraint { - { NameOfCoef Uz; - EntityType Region; NameOfConstraint Voltage_Cir; } - { NameOfCoef Iz; - EntityType Region; NameOfConstraint Current_Cir; } - } - } - } -EndIf - - -// Static Formulation -Formulation { - { Name MagSta_a_2D; Type FemEquation; - Quantity { - { Name a; Type Local; NameOfSpace Hcurl_a_2D; } - { Name ir; Type Local; NameOfSpace Hregion_i_2D; } - } - Equation { - Integral { [ nu[] * Dof{d a} , {d a} ]; - In Vol_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ -nu[] * br[] , {d a} ]; - In Vol_M_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ -js0[] , {a} ]; - In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ - (js0[]*Vector[0,0,1]) * Dof{ir} , {a} ]; - In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ nxh[] , {a} ]; - In Sur_FluxTube_Mag; Jacobian Sur; Integration Gauss_v; } - } - } -} - -// Dynamic Formulation (eddy currents) -Formulation { - { Name MagDyn_a_2D; Type FemEquation; - Quantity { - { Name a; Type Local; NameOfSpace Hcurl_a_2D; } - { Name A_floating; Type Global; NameOfSpace Hcurl_a_2D [A]; } - { Name I_perfect; Type Global; NameOfSpace Hcurl_a_2D [I]; } - - { Name ur; Type Local; NameOfSpace Hregion_u_2D; } - { Name I; Type Global; NameOfSpace Hregion_u_2D [I]; } - { Name U; Type Global; NameOfSpace Hregion_u_2D [U]; } - - { Name ir; Type Local; NameOfSpace Hregion_i_2D; } - { Name Us; Type Global; NameOfSpace Hregion_i_2D [Us]; } - { Name Is; Type Global; NameOfSpace Hregion_i_2D [Is]; } - - If(Flag_CircuitCoupling) - { Name Uz; Type Global; NameOfSpace Hregion_Z [Uz]; } - { Name Iz; Type Global; NameOfSpace Hregion_Z [Iz]; } - EndIf - } - Equation { - Integral { [ nu[] * Dof{d a} , {d a} ]; - In Vol_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ -nu[] * br[] , {d a} ]; - In Vol_M_Mag; Jacobian Vol; Integration Gauss_v; } - - // Electric field e = -Dt[{a}]-{ur}, - // with {ur} = Grad v constant in each region of Vol_C_Mag - Integral { DtDof [ sigma[] * Dof{a} , {a} ]; - In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ sigma[] * Dof{ur} / CoefGeos[] , {a} ]; - In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ - sigma[] * (Velocity[] /\ Dof{d a}) , {a} ]; - In Vol_V_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ -js0[] , {a} ]; - In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { [ nxh[] , {a} ]; - In Sur_FluxTube_Mag; Jacobian Sur; Integration Gauss_v; } - - Integral { DtDof [ Ysur[] * Dof{a} , {a} ]; - In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } - Integral { [ Ysur[] * Dof{ur} / CoefGeos[] , {a} ]; - In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } - - // When {ur} act as a test function, one obtains the circuits relations, - // relating the voltage and the current of each region in Vol_C_Mag - Integral { DtDof [ sigma[] * Dof{a} , {ur} ]; - In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ sigma[] * Dof{ur} / CoefGeos[] , {ur} ]; - In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } - GlobalTerm { [ Dof{I} *(CoefGeos[]/Fabs[CoefGeos[]]) , {U} ]; In Vol_C_Mag; } - - Integral { DtDof [ Ysur[] * Dof{a} , {ur} ]; - In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } - Integral { [ Ysur[] * Dof{ur} / CoefGeos[] , {ur} ]; - In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } - GlobalTerm { [ Dof{I} *(CoefGeos[]/Fabs[CoefGeos[]]) , {U} ]; In Sur_Imped_Mag; } - - // js[0] should be of the form: Ns[]/Sc[] * Vector[0,0,1] - Integral { [ - (js0[]*Vector[0,0,1]) * Dof{ir} , {a} ]; - In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } - - Integral { DtDof [ Ns[]/Sc[] * Dof{a} , {ir} ]; - In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ Ns[]/Sc[] / sigma[] * (js0[]*Vector[0,0,1]) * Dof{ir} , {ir} ]; - In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } - GlobalTerm { [ Dof{Us} / CoefGeos[] , {Is} ]; In Vol_S_Mag; } - // Attention: CoefGeo[.] = 2*Pi for Axi - - GlobalTerm { [ -Dof{I_perfect} , {A_floating} ]; In Sur_Perfect_Mag; } - - If(Flag_CircuitCoupling) - GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ]; In Resistance_Cir; } - GlobalTerm { NeverDt[ Resistance[] * Dof{Iz} , {Iz} ]; In Resistance_Cir; } - - GlobalTerm { [ Dof{Uz} , {Iz} ]; In Inductance_Cir; } - GlobalTerm { DtDof [ Inductance[] * Dof{Iz} , {Iz} ]; In Inductance_Cir; } - - GlobalTerm { NeverDt[ Dof{Iz} , {Iz} ]; In Capacitance_Cir; } - GlobalTerm { DtDof [ Capacitance[] * Dof{Uz} , {Iz} ]; In Capacitance_Cir; } - - GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ]; In Diode_Cir; } - GlobalTerm { NeverDt[ Resistance[{Uz}] * Dof{Iz} , {Iz} ]; In Diode_Cir; } - - GlobalTerm { [ 0. * Dof{Iz} , {Iz} ]; In DomainSource_Cir; } - - GlobalEquation { - Type Network; NameOfConstraint ElectricalCircuit; - { Node {I}; Loop {U}; Equation {I}; In Vol_C_Mag; } - { Node {Is}; Loop {Us}; Equation {Us}; In Vol_S_Mag; } - { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } - } - EndIf - - } - } -} - -Resolution { - { Name MagDyn_a_2D; - System { - { Name Sys; NameOfFormulation MagDyn_a_2D; - If(Flag_FrequencyDomain) - Type ComplexValue; Frequency Freq; - EndIf - } - } - Operation { - If(Flag_FrequencyDomain) - Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; - Else - InitSolution[Sys]; // provide initial condition - TimeLoopTheta[TimeInit, TimeFinal, DeltaTime, 1.]{ - // Euler implicit (1) -- Crank-Nicolson (0.5) - Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; - } - EndIf - } - } - { Name MagSta_a_2D; - System { - { Name Sys; NameOfFormulation MagSta_a_2D; } - } - Operation { - Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; - } - } -} - -// Same PostProcessing for both static and dynamic formulations (both refer to -// the same FunctionSpace from which the solution is obtained) -PostProcessing { - { Name MagDyn_a_2D; NameOfFormulation MagDyn_a_2D; - PostQuantity { - // In 2D, a is a vector with only a z-component: (0,0,az) - { Name a; Value { - Term { [ {a} ]; In Vol_Mag; Jacobian Vol; } - } - } - // The equilines of az are field lines (giving the magnetic field direction) - { Name az; Value { - Term { [ CompZ[{a}] ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name b; Value { - Term { [ {d a} ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name h; Value { - Term { [ nu[] * {d a} ]; In Vol_Mag; Jacobian Vol; } - Term { [ -nu[] * br[] ]; In Vol_M_Mag; Jacobian Vol; } - } - } - { Name js; Value { - Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } - Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } - Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } // to force a vector result out of sources - } - } - { Name j; Value { - Term { [ -sigma[] * (Dt[{a}]+{ur}/CoefGeos[]) ]; In Vol_C_Mag; Jacobian Vol; } - Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } - Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } - Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } - // Current density in A/m - Term { [ -Ysur[] * (Dt[{a}]+{ur}/CoefGeos[]) ]; In Sur_Imped_Mag; Jacobian Sur; } - } - } - { Name JouleLosses; Value { - Integral { [ CoefPower * sigma[]*SquNorm[Dt[{a}]+{ur}/CoefGeos[]] ]; - In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ CoefPower * 1./sigma[]*SquNorm[js0[]] ]; - In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ CoefPower * 1./sigma[]*SquNorm[(js0[]*Vector[0,0,1])*{ir}] ]; - In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } - Integral { [ CoefPower * Ysur[]*SquNorm[Dt[{a}]+{ur}/CoefGeos[]] ]; - In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } - } - } - { Name U; Value { - Term { [ {U} ]; In Vol_C_Mag; } - Term { [ {Us} ]; In Vol_S_Mag; } - If(Flag_CircuitCoupling) - Term { [ {Uz} ]; In Domain_Cir; } - EndIf - } - } - { Name I; Value { - Term { [ {I} ]; In Vol_C_Mag; } - Term { [ {Is} ]; In Vol_S_Mag; } - If(Flag_CircuitCoupling) - Term { [ {Iz} ]; In Domain_Cir; } - EndIf - } - } - } - } - - { Name MagSta_a_2D; NameOfFormulation MagSta_a_2D; - PostQuantity { - { Name a; Value { - Term { [ {a} ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name az; Value { - Term { [ CompZ[{a}] ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name b; Value { - Term { [ {d a} ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name h; Value { - Term { [ nu[] * {d a} ]; In Vol_Mag; Jacobian Vol; } - } - } - { Name j; Value { - Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } - Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } - Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } - } - } - } - } -} +// This is a template .pro file containing a general formulation for 2D +// magnetostatic and magnetodynamic problems in terms of the magnetic vector +// potential a (potentially coupled with the electric scalar potential v), with +// optional circuit coupling. + +// Below are definitions of the constants (inside "DefineConstant"), groups +// (inside "DefineGroup") and functions (inside "DefineFunction") that can be +// redefined from outside this template. + +DefineConstant[ + Flag_FrequencyDomain = 1, // frequency-domain or time-domain simulation + Flag_CircuitCoupling = 0 // consider coupling with external electric circuit + CoefPower = 0.5, // coefficient for power calculations + Freq = 50, // frequency (for harmonic simulations) + TimeInit = 0, // intial time (for time-domain simulations) + TimeFinal = 1/50, // final time (for time-domain simulations) + DeltaTime = 1/500, // time step (for time-domain simulations) + FE_Order = 1 // finite element order + Val_Rint = 0, // interior radius of annulus shell transformation region (Vol_Inf_Mag) + Val_Rext = 0 // exterior radius of annulus shell transformation region (Vol_Inf_Mag) +]; + +Group { + DefineGroup[ + Vol_CC_Mag, // the non-conducting part + Vol_C_Mag, // the conducting part + Vol_V_Mag, // a moving conducting part, with invariant mesh + Vol_M_Mag, // permanent magnets + Vol_S0_Mag, // current source domain with imposed current densities js0 + Vol_S_Mag, // current source domain with imposed current, imposed voltage or + // circuit coupling + Vol_Inf_Mag, // annulus where a infinite shell transformation is applied + Sur_FluxTube_Mag, // boundary with Neumann BC + Sur_Perfect_Mag, // boundary of perfect conductors (i.e. non-meshed) + Sur_Imped_Mag // boundary of conductors approximated by a surface impedance + // (i.e. non-meshed) + ]; + If(Flag_CircuitCoupling) + DefineGroup[ + SourceV_Cir, // voltage sources + SourceI_Cir, // current sources + Resistance_Cir, // resistors (linear) + Inductance_Cir, // inductors + Capacitance_Cir, // capacitors + Diode_Cir // diodes (treated as nonlinear resistors) + ]; + EndIf +} + +Function { + DefineFunction[ + nu, // reluctivity (in Vol_Mag) + sigma, // conductivity (in Vol_C_Mag and Vol_S_Mag) + br, // remanent magnetic flux density (in Vol_M_Mag) + js0, // source current density (in Vol_S0_Mag) + nxh, // n x magnetic field (on Sur_FluxTube_Mag) + Velocity, // velocity of moving part Vol_V_Mag + Ns, // number of turns (in Vol_S_Mag) + Sc, // cross-section of windings (in Vol_S_Mag) + CoefGeos, // geometrical coefficient for 2D or 2D axi model + Ysur // surface admittance (inverse of surface impedance Zsur) on Sur_Imped_Mag + ]; + If(Flag_CircuitCoupling) + DefineFunction[ + Resistance, // resistance values + Inductance, // inductance values + Capacitance // capacitance values + ]; + EndIf +} + +// End of definitions. + +Group{ + // all volumes + Vol_Mag = Region[ {Vol_CC_Mag, Vol_C_Mag, Vol_V_Mag, Vol_M_Mag, Vol_S0_Mag, Vol_S_Mag} ]; + // all volumes + surfaces on which integrals will be computed + Dom_Mag = Region[ {Vol_Mag, Sur_FluxTube_Mag, Sur_Perfect_Mag, Sur_Imped_Mag} ]; + If(Flag_CircuitCoupling) + // all circuit impedances + DomainZ_Cir = Region[ {Resistance_Cir, Inductance_Cir, Capacitance_Cir} ]; + // all circuit sources + DomainSource_Cir = Region[ {SourceV_Cir, SourceI_Cir} ]; + // all circuit elements + Domain_Cir = Region[ {DomainZ_Cir, DomainSource_Cir} ]; + EndIf +} + +Jacobian { + { Name Vol; + Case { + { Region Vol_Inf_Mag ; + Jacobian VolSphShell {Val_Rint, Val_Rext} ; } + { Region All; Jacobian Vol; } + } + } + { Name Sur; + Case { + { Region All; Jacobian Sur; } + } + } +} + +Integration { + { Name Gauss_v; + Case { + { Type Gauss; + Case { + { GeoElement Point; NumberOfPoints 1; } + { GeoElement Line; NumberOfPoints 5; } + { GeoElement Triangle; NumberOfPoints 7; } + { GeoElement Quadrangle; NumberOfPoints 4; } + { GeoElement Tetrahedron; NumberOfPoints 15; } + { GeoElement Hexahedron; NumberOfPoints 14; } + { GeoElement Prism; NumberOfPoints 21; } + } + } + } + } +} + +// Same FunctionSpace for both static and dynamic formulations +FunctionSpace { + { Name Hcurl_a_2D; Type Form1P; // 1-form (circulations) on edges + // perpendicular to the plane of study + BasisFunction { + // \vec{a}(x) = \sum_{n \in N(Domain)} a_n \vec{s}_n(x) + // without nodes on perfect conductors (where a is constant) + { Name s_n; NameOfCoef a_n; Function BF_PerpendicularEdge; + Support Dom_Mag; Entity NodesOf[All, Not Sur_Perfect_Mag]; } + + // global basis function on boundary of perfect conductors + { Name s_skin; NameOfCoef a_skin; Function BF_GroupOfPerpendicularEdges; + Support Dom_Mag; Entity GroupsOfNodesOf[Sur_Perfect_Mag]; } + + // additional basis functions for 2nd order interpolation + If(FE_Order == 2) + { Name s_e; NameOfCoef a_e; Function BF_PerpendicularEdge_2E; + Support Vol_Mag; Entity EdgesOf[All]; } + EndIf + } + GlobalQuantity { + { Name A; Type AliasOf; NameOfCoef a_skin; } + { Name I; Type AssociatedWith; NameOfCoef a_skin; } + } + Constraint { + { NameOfCoef a_n; + EntityType NodesOf; NameOfConstraint MagneticVectorPotential_2D; } + + { NameOfCoef I; + EntityType GroupsOfNodesOf; NameOfConstraint Current_2D; } + + If(FE_Order == 2) + { NameOfCoef a_e; + EntityType EdgesOf; NameOfConstraint MagneticVectorPotential_2D_0; } + EndIf + } + } +} + +FunctionSpace { + // Gradient of Electric scalar potential (2D) + { Name Hregion_u_2D; Type Form1P; // same as for \vec{a} + BasisFunction { + { Name sr; NameOfCoef ur; Function BF_RegionZ; + // constant vector (over the region) with nonzero z-component only + Support Region[{Vol_C_Mag, Sur_Imped_Mag}]; + Entity Region[{Vol_C_Mag, Sur_Imped_Mag}]; } + } + GlobalQuantity { + { Name U; Type AliasOf; NameOfCoef ur; } + { Name I; Type AssociatedWith; NameOfCoef ur; } + } + Constraint { + { NameOfCoef U; + EntityType Region; NameOfConstraint Voltage_2D; } + { NameOfCoef I; + EntityType Region; NameOfConstraint Current_2D; } + } + } + + // Current in stranded coil (2D) + { Name Hregion_i_2D; Type Vector; + BasisFunction { + { Name sr; NameOfCoef ir; Function BF_RegionZ; + Support Vol_S_Mag; Entity Vol_S_Mag; } + } + GlobalQuantity { + { Name Is; Type AliasOf; NameOfCoef ir; } + { Name Us; Type AssociatedWith; NameOfCoef ir; } + } + Constraint { + { NameOfCoef Us; + EntityType Region; NameOfConstraint Voltage_2D; } + { NameOfCoef Is; + EntityType Region; NameOfConstraint Current_2D; } + } + } +} + +If(Flag_CircuitCoupling) + // UZ and IZ for impedances + FunctionSpace { + { Name Hregion_Z; Type Scalar; + BasisFunction { + { Name sr; NameOfCoef ir; Function BF_Region; + Support Domain_Cir; Entity Domain_Cir; } + } + GlobalQuantity { + { Name Iz; Type AliasOf; NameOfCoef ir; } + { Name Uz; Type AssociatedWith; NameOfCoef ir; } + } + Constraint { + { NameOfCoef Uz; + EntityType Region; NameOfConstraint Voltage_Cir; } + { NameOfCoef Iz; + EntityType Region; NameOfConstraint Current_Cir; } + } + } + } +EndIf + + +// Static Formulation +Formulation { + { Name MagSta_a_2D; Type FemEquation; + Quantity { + { Name a; Type Local; NameOfSpace Hcurl_a_2D; } + { Name ir; Type Local; NameOfSpace Hregion_i_2D; } + } + Equation { + Integral { [ nu[] * Dof{d a} , {d a} ]; + In Vol_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ -nu[] * br[] , {d a} ]; + In Vol_M_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ -js0[] , {a} ]; + In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ - (js0[]*Vector[0,0,1]) * Dof{ir} , {a} ]; + In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ nxh[] , {a} ]; + In Sur_FluxTube_Mag; Jacobian Sur; Integration Gauss_v; } + } + } +} + +// Dynamic Formulation (eddy currents) +Formulation { + { Name MagDyn_a_2D; Type FemEquation; + Quantity { + { Name a; Type Local; NameOfSpace Hcurl_a_2D; } + { Name A_floating; Type Global; NameOfSpace Hcurl_a_2D [A]; } + { Name I_perfect; Type Global; NameOfSpace Hcurl_a_2D [I]; } + + { Name ur; Type Local; NameOfSpace Hregion_u_2D; } + { Name I; Type Global; NameOfSpace Hregion_u_2D [I]; } + { Name U; Type Global; NameOfSpace Hregion_u_2D [U]; } + + { Name ir; Type Local; NameOfSpace Hregion_i_2D; } + { Name Us; Type Global; NameOfSpace Hregion_i_2D [Us]; } + { Name Is; Type Global; NameOfSpace Hregion_i_2D [Is]; } + + If(Flag_CircuitCoupling) + { Name Uz; Type Global; NameOfSpace Hregion_Z [Uz]; } + { Name Iz; Type Global; NameOfSpace Hregion_Z [Iz]; } + EndIf + } + Equation { + Integral { [ nu[] * Dof{d a} , {d a} ]; + In Vol_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ -nu[] * br[] , {d a} ]; + In Vol_M_Mag; Jacobian Vol; Integration Gauss_v; } + + // Electric field e = -Dt[{a}]-{ur}, + // with {ur} = Grad v constant in each region of Vol_C_Mag + Integral { DtDof [ sigma[] * Dof{a} , {a} ]; + In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ sigma[] * Dof{ur} / CoefGeos[] , {a} ]; + In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ - sigma[] * (Velocity[] /\ Dof{d a}) , {a} ]; + In Vol_V_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ -js0[] , {a} ]; + In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { [ nxh[] , {a} ]; + In Sur_FluxTube_Mag; Jacobian Sur; Integration Gauss_v; } + + Integral { DtDof [ Ysur[] * Dof{a} , {a} ]; + In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } + Integral { [ Ysur[] * Dof{ur} / CoefGeos[] , {a} ]; + In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } + + // When {ur} act as a test function, one obtains the circuits relations, + // relating the voltage and the current of each region in Vol_C_Mag + Integral { DtDof [ sigma[] * Dof{a} , {ur} ]; + In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ sigma[] * Dof{ur} / CoefGeos[] , {ur} ]; + In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } + GlobalTerm { [ Dof{I} *(CoefGeos[]/Fabs[CoefGeos[]]) , {U} ]; In Vol_C_Mag; } + + Integral { DtDof [ Ysur[] * Dof{a} , {ur} ]; + In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } + Integral { [ Ysur[] * Dof{ur} / CoefGeos[] , {ur} ]; + In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } + GlobalTerm { [ Dof{I} *(CoefGeos[]/Fabs[CoefGeos[]]) , {U} ]; In Sur_Imped_Mag; } + + // js[0] should be of the form: Ns[]/Sc[] * Vector[0,0,1] + Integral { [ - (js0[]*Vector[0,0,1]) * Dof{ir} , {a} ]; + In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } + + Integral { DtDof [ Ns[]/Sc[] * Dof{a} , {ir} ]; + In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ Ns[]/Sc[] / sigma[] * (js0[]*Vector[0,0,1]) * Dof{ir} , {ir} ]; + In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } + GlobalTerm { [ Dof{Us} / CoefGeos[] , {Is} ]; In Vol_S_Mag; } + // Attention: CoefGeo[.] = 2*Pi for Axi + + GlobalTerm { [ -Dof{I_perfect} , {A_floating} ]; In Sur_Perfect_Mag; } + + If(Flag_CircuitCoupling) + GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ]; In Resistance_Cir; } + GlobalTerm { NeverDt[ Resistance[] * Dof{Iz} , {Iz} ]; In Resistance_Cir; } + + GlobalTerm { [ Dof{Uz} , {Iz} ]; In Inductance_Cir; } + GlobalTerm { DtDof [ Inductance[] * Dof{Iz} , {Iz} ]; In Inductance_Cir; } + + GlobalTerm { NeverDt[ Dof{Iz} , {Iz} ]; In Capacitance_Cir; } + GlobalTerm { DtDof [ Capacitance[] * Dof{Uz} , {Iz} ]; In Capacitance_Cir; } + + GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ]; In Diode_Cir; } + GlobalTerm { NeverDt[ Resistance[{Uz}] * Dof{Iz} , {Iz} ]; In Diode_Cir; } + + GlobalTerm { [ 0. * Dof{Iz} , {Iz} ]; In DomainSource_Cir; } + + GlobalEquation { + Type Network; NameOfConstraint ElectricalCircuit; + { Node {I}; Loop {U}; Equation {I}; In Vol_C_Mag; } + { Node {Is}; Loop {Us}; Equation {Us}; In Vol_S_Mag; } + { Node {Iz}; Loop {Uz}; Equation {Uz}; In Domain_Cir; } + } + EndIf + + } + } +} + +Resolution { + { Name MagDyn_a_2D; + System { + { Name Sys; NameOfFormulation MagDyn_a_2D; + If(Flag_FrequencyDomain) + Type ComplexValue; Frequency Freq; + EndIf + } + } + Operation { + If(Flag_FrequencyDomain) + Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; + Else + InitSolution[Sys]; // provide initial condition + TimeLoopTheta[TimeInit, TimeFinal, DeltaTime, 1.]{ + // Euler implicit (1) -- Crank-Nicolson (0.5) + Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; + } + EndIf + } + } + { Name MagSta_a_2D; + System { + { Name Sys; NameOfFormulation MagSta_a_2D; } + } + Operation { + Generate[Sys]; Solve[Sys]; SaveSolution[Sys]; + } + } +} + +// Same PostProcessing for both static and dynamic formulations (both refer to +// the same FunctionSpace from which the solution is obtained) +PostProcessing { + { Name MagDyn_a_2D; NameOfFormulation MagDyn_a_2D; + PostQuantity { + // In 2D, a is a vector with only a z-component: (0,0,az) + { Name a; Value { + Term { [ {a} ]; In Vol_Mag; Jacobian Vol; } + } + } + // The equilines of az are field lines (giving the magnetic field direction) + { Name az; Value { + Term { [ CompZ[{a}] ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name b; Value { + Term { [ {d a} ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name h; Value { + Term { [ nu[] * {d a} ]; In Vol_Mag; Jacobian Vol; } + Term { [ -nu[] * br[] ]; In Vol_M_Mag; Jacobian Vol; } + } + } + { Name js; Value { + Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } + Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } + Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } // to force a vector result out of sources + } + } + { Name j; Value { + Term { [ -sigma[] * (Dt[{a}]+{ur}/CoefGeos[]) ]; In Vol_C_Mag; Jacobian Vol; } + Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } + Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } + Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } + // Current density in A/m + Term { [ -Ysur[] * (Dt[{a}]+{ur}/CoefGeos[]) ]; In Sur_Imped_Mag; Jacobian Sur; } + } + } + { Name JouleLosses; Value { + Integral { [ CoefPower * sigma[]*SquNorm[Dt[{a}]+{ur}/CoefGeos[]] ]; + In Vol_C_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ CoefPower * 1./sigma[]*SquNorm[js0[]] ]; + In Vol_S0_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ CoefPower * 1./sigma[]*SquNorm[(js0[]*Vector[0,0,1])*{ir}] ]; + In Vol_S_Mag; Jacobian Vol; Integration Gauss_v; } + Integral { [ CoefPower * Ysur[]*SquNorm[Dt[{a}]+{ur}/CoefGeos[]] ]; + In Sur_Imped_Mag; Jacobian Sur; Integration Gauss_v; } + } + } + { Name U; Value { + Term { [ {U} ]; In Vol_C_Mag; } + Term { [ {Us} ]; In Vol_S_Mag; } + If(Flag_CircuitCoupling) + Term { [ {Uz} ]; In Domain_Cir; } + EndIf + } + } + { Name I; Value { + Term { [ {I} ]; In Vol_C_Mag; } + Term { [ {Is} ]; In Vol_S_Mag; } + If(Flag_CircuitCoupling) + Term { [ {Iz} ]; In Domain_Cir; } + EndIf + } + } + } + } + + { Name MagSta_a_2D; NameOfFormulation MagSta_a_2D; + PostQuantity { + { Name a; Value { + Term { [ {a} ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name az; Value { + Term { [ CompZ[{a}] ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name b; Value { + Term { [ {d a} ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name h; Value { + Term { [ nu[] * {d a} ]; In Vol_Mag; Jacobian Vol; } + } + } + { Name j; Value { + Term { [ js0[] ]; In Vol_S0_Mag; Jacobian Vol; } + Term { [ (js0[]*Vector[0,0,1])*{ir} ]; In Vol_S_Mag; Jacobian Vol; } + Term { [ Vector[0,0,0] ]; In Vol_Mag; Jacobian Vol; } + } + } + } + } +} diff --git a/Magnetodynamics/electromagnet.geo b/Magnetodynamics/electromagnet.geo index b24c084..7bd410c 100644 --- a/Magnetodynamics/electromagnet.geo +++ b/Magnetodynamics/electromagnet.geo @@ -1,54 +1,54 @@ -/* ------------------------------------------------------------------- - File "electromagnet.geo" - - This file is the geometrical description used by GMSH to produce - the file "electromagnet.msh". - ------------------------------------------------------------------- */ - -dxCore = 50.e-3; dyCore = 100.e-3; -xInd = 75.e-3; dxInd = 25.e-3; dyInd = 50.e-3; - -Include "electromagnet_common.pro"; - -s = DefineNumber[1, Name "Model parameters/Global mesh size", - Help "Reduce for finer mesh"]; -p0 = 12.e-3 *s; -pCorex = 4.e-3 *s; pCorey0 = 8.e-3 *s; pCorey = 4.e-3 *s; -pIndx = 5.e-3 *s; pIndy = 5.e-3 *s; -pInt = 12.5e-3*s; pExt = 12.5e-3*s; - -Point(1) = {0,0,0,p0}; -Point(2) = {dxCore,0,0,pCorex}; -Point(3) = {dxCore,dyCore,0,pCorey}; -Point(4) = {0,dyCore,0,pCorey0}; -Point(5) = {xInd,0,0,pIndx}; -Point(6) = {xInd+dxInd,0,0,pIndx}; -Point(7) = {xInd+dxInd,dyInd,0,pIndy}; -Point(8) = {xInd,dyInd,0,pIndy}; -Point(9) = {rInt,0,0,pInt}; -Point(10) = {rExt,0,0,pExt}; -Point(11) = {0,rInt,0,pInt}; -Point(12) = {0,rExt,0,pExt}; - -Line(1) = {1,2}; Line(2) = {2,5}; Line(3) = {5,6}; -Line(4) = {6,9}; Line(5) = {9,10}; Line(6) = {1,4}; -Line(7) = {4,11}; Line(8) = {11,12}; Line(9) = {2,3}; -Line(10) = {3,4}; Line(11) = {6,7}; Line(12) = {7,8}; -Line(13) = {8,5}; - -Circle(14) = {9,1,11}; Circle(15) = {10,1,12}; - -Line Loop(16) = {-6,1,9,10}; Plane Surface(17) = {16}; -Line Loop(18) = {11,12,13,3}; Plane Surface(19) = {18}; -Line Loop(20) = {7,-14,-4,11,12,13,-2,9,10}; Plane Surface(21) = {-20}; // "-" for orientation -Line Loop(22) = {8,-15,-5,14}; Plane Surface(23) = {-22}; - -Physical Surface(101) = {21}; /* Air */ -Physical Surface(102) = {17}; /* Core */ -Physical Surface(103) = {19}; /* Ind */ -Physical Surface(111) = {23}; /* AirInf */ - -Physical Line(1100) = {1,2,3,4,5}; /* Surface ht = 0 */ -Physical Line(1101) = {6,7,8}; /* Surface bn = 0 */ -Physical Line(1102) = {15}; /* Surface Inf */ - +/* ------------------------------------------------------------------- + File "electromagnet.geo" + + This file is the geometrical description used by GMSH to produce + the file "electromagnet.msh". + ------------------------------------------------------------------- */ + +dxCore = 50.e-3; dyCore = 100.e-3; +xInd = 75.e-3; dxInd = 25.e-3; dyInd = 50.e-3; + +Include "electromagnet_common.pro"; + +s = DefineNumber[1, Name "Model parameters/Global mesh size", + Help "Reduce for finer mesh"]; +p0 = 12.e-3 *s; +pCorex = 4.e-3 *s; pCorey0 = 8.e-3 *s; pCorey = 4.e-3 *s; +pIndx = 5.e-3 *s; pIndy = 5.e-3 *s; +pInt = 12.5e-3*s; pExt = 12.5e-3*s; + +Point(1) = {0,0,0,p0}; +Point(2) = {dxCore,0,0,pCorex}; +Point(3) = {dxCore,dyCore,0,pCorey}; +Point(4) = {0,dyCore,0,pCorey0}; +Point(5) = {xInd,0,0,pIndx}; +Point(6) = {xInd+dxInd,0,0,pIndx}; +Point(7) = {xInd+dxInd,dyInd,0,pIndy}; +Point(8) = {xInd,dyInd,0,pIndy}; +Point(9) = {rInt,0,0,pInt}; +Point(10) = {rExt,0,0,pExt}; +Point(11) = {0,rInt,0,pInt}; +Point(12) = {0,rExt,0,pExt}; + +Line(1) = {1,2}; Line(2) = {2,5}; Line(3) = {5,6}; +Line(4) = {6,9}; Line(5) = {9,10}; Line(6) = {1,4}; +Line(7) = {4,11}; Line(8) = {11,12}; Line(9) = {2,3}; +Line(10) = {3,4}; Line(11) = {6,7}; Line(12) = {7,8}; +Line(13) = {8,5}; + +Circle(14) = {9,1,11}; Circle(15) = {10,1,12}; + +Line Loop(16) = {-6,1,9,10}; Plane Surface(17) = {16}; +Line Loop(18) = {11,12,13,3}; Plane Surface(19) = {18}; +Line Loop(20) = {7,-14,-4,11,12,13,-2,9,10}; Plane Surface(21) = {-20}; // "-" for orientation +Line Loop(22) = {8,-15,-5,14}; Plane Surface(23) = {-22}; + +Physical Surface(101) = {21}; /* Air */ +Physical Surface(102) = {17}; /* Core */ +Physical Surface(103) = {19}; /* Ind */ +Physical Surface(111) = {23}; /* AirInf */ + +Physical Line(1100) = {1,2,3,4,5}; /* Surface ht = 0 */ +Physical Line(1101) = {6,7,8}; /* Surface bn = 0 */ +Physical Line(1102) = {15}; /* Surface Inf */ + diff --git a/Magnetodynamics/electromagnet.pro b/Magnetodynamics/electromagnet.pro index 29a9429..4c48dca 100644 --- a/Magnetodynamics/electromagnet.pro +++ b/Magnetodynamics/electromagnet.pro @@ -1,89 +1,89 @@ -/* ------------------------------------------------------------------- - Tutorial 7a : magnetic fields of an electromagnet - - Features: - - Use of a template formulation library - - Identical to Tutorial 2 for a static current source - - Frequency-domain solution (phasor) for a dynamic current source - - To compute the static solution in a terminal: - getdp electromagnet -solve MagSta_a_2D -pos Map_a - - To compute the time-harmonic dynamic solution in a terminal: - getdp electromagnet -solve MagDyn_a_2D -pos Map_a - - To compute the solution interactively from the Gmsh GUI: - File > Open > electromagnet.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -Include "electromagnet_common.pro"; - -Group { - // Physical regions - Air = Region[ 101 ]; Core = Region[ 102 ]; - Ind = Region[ 103 ]; AirInf = Region[ 111 ]; - Surface_ht0 = Region[ 1100 ]; - Surface_bn0 = Region[ 1101 ]; - Surface_Inf = Region[ 1102 ]; - - // Abstract regions used in the "Lib_MagStaDyn_av_2D_Cir.pro" template file - // that is included below: - Vol_CC_Mag = Region[{Air, AirInf}]; // Non-conducting regions - Vol_C_Mag = Region[{Core}]; // Massive conducting regions - Vol_S_Mag = Region[{Ind}]; // Stranded conductors, i.e., coils - Vol_Inf_Mag = Region[{AirInf}]; // Annulus for infinite shell transformation - Val_Rint = rInt; Val_Rext = rExt; // Interior and exterior radii of annulus -} - -Function { - DefineConstant[ - murCore = {100, Name "Model parameters/Mur core"}, - Current = {0.01, Name "Model parameters/Current"} - ]; - - mu0 = 4.e-7 * Pi; - nu[ Region[{Air, Ind, AirInf}] ] = 1. / mu0; - nu[ Core ] = 1. / (murCore * mu0); - - sigma[ Core ] = 1e6 / 10; - sigma[ Ind ] = 5e7; - - Ns[ Ind ] = 1000 ; // number of turns in coil - Sc[ Ind ] = SurfaceArea[] ; // surface (cross section) of coil - // Current density in each coil portion for a unit current (will be multiplied - // by the actual total current in the coil) - js0[ Ind ] = Ns[]/Sc[] * Vector[0,0,-1]; - CoefGeos[] = 1; -} - -Constraint { - { Name MagneticVectorPotential_2D; - Case { - { Region Surface_bn0; Value 0; } - { Region Surface_Inf; Value 0; } - } - } - { Name Current_2D; - Case { - // represents the phasor amplitude for a dynamic analysis - { Region Ind; Value Current; } - } - } - { Name Voltage_2D; - Case { - { Region Core; Value 0; } - } - } -} - -Include "Lib_MagStaDyn_av_2D_Cir.pro"; - -PostOperation { - { Name Map_a; NameOfPostProcessing MagDyn_a_2D; - Operation { - Print[ a, OnElementsOf Vol_Mag, File "a.pos" ]; - Print[ b, OnElementsOf Vol_Mag, File "b.pos" , HarmonicToTime 20]; - } - } -} +/* ------------------------------------------------------------------- + Tutorial 7a : magnetic fields of an electromagnet + + Features: + - Use of a template formulation library + - Identical to Tutorial 2 for a static current source + - Frequency-domain solution (phasor) for a dynamic current source + + To compute the static solution in a terminal: + getdp electromagnet -solve MagSta_a_2D -pos Map_a + + To compute the time-harmonic dynamic solution in a terminal: + getdp electromagnet -solve MagDyn_a_2D -pos Map_a + + To compute the solution interactively from the Gmsh GUI: + File > Open > electromagnet.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +Include "electromagnet_common.pro"; + +Group { + // Physical regions + Air = Region[ 101 ]; Core = Region[ 102 ]; + Ind = Region[ 103 ]; AirInf = Region[ 111 ]; + Surface_ht0 = Region[ 1100 ]; + Surface_bn0 = Region[ 1101 ]; + Surface_Inf = Region[ 1102 ]; + + // Abstract regions used in the "Lib_MagStaDyn_av_2D_Cir.pro" template file + // that is included below: + Vol_CC_Mag = Region[{Air, AirInf}]; // Non-conducting regions + Vol_C_Mag = Region[{Core}]; // Massive conducting regions + Vol_S_Mag = Region[{Ind}]; // Stranded conductors, i.e., coils + Vol_Inf_Mag = Region[{AirInf}]; // Annulus for infinite shell transformation + Val_Rint = rInt; Val_Rext = rExt; // Interior and exterior radii of annulus +} + +Function { + DefineConstant[ + murCore = {100, Name "Model parameters/Mur core"}, + Current = {0.01, Name "Model parameters/Current"} + ]; + + mu0 = 4.e-7 * Pi; + nu[ Region[{Air, Ind, AirInf}] ] = 1. / mu0; + nu[ Core ] = 1. / (murCore * mu0); + + sigma[ Core ] = 1e6 / 10; + sigma[ Ind ] = 5e7; + + Ns[ Ind ] = 1000 ; // number of turns in coil + Sc[ Ind ] = SurfaceArea[] ; // surface (cross section) of coil + // Current density in each coil portion for a unit current (will be multiplied + // by the actual total current in the coil) + js0[ Ind ] = Ns[]/Sc[] * Vector[0,0,-1]; + CoefGeos[] = 1; +} + +Constraint { + { Name MagneticVectorPotential_2D; + Case { + { Region Surface_bn0; Value 0; } + { Region Surface_Inf; Value 0; } + } + } + { Name Current_2D; + Case { + // represents the phasor amplitude for a dynamic analysis + { Region Ind; Value Current; } + } + } + { Name Voltage_2D; + Case { + { Region Core; Value 0; } + } + } +} + +Include "Lib_MagStaDyn_av_2D_Cir.pro"; + +PostOperation { + { Name Map_a; NameOfPostProcessing MagDyn_a_2D; + Operation { + Print[ a, OnElementsOf Vol_Mag, File "a.pos" ]; + Print[ b, OnElementsOf Vol_Mag, File "b.pos" , HarmonicToTime 20]; + } + } +} diff --git a/Magnetodynamics/electromagnet_common.pro b/Magnetodynamics/electromagnet_common.pro index f0dd285..56879cd 100644 --- a/Magnetodynamics/electromagnet_common.pro +++ b/Magnetodynamics/electromagnet_common.pro @@ -1,4 +1,4 @@ -// Parameters shared by Gmsh and GetDP - -rInt = 200.e-3; -rExt = 250.e-3; +// Parameters shared by Gmsh and GetDP + +rInt = 200.e-3; +rExt = 250.e-3; diff --git a/Magnetodynamics/transfo.geo b/Magnetodynamics/transfo.geo index 6243d4b..072bc9b 100644 --- a/Magnetodynamics/transfo.geo +++ b/Magnetodynamics/transfo.geo @@ -1,173 +1,173 @@ - -Include "transfo_common.pro"; - -Solver.AutoShowLastStep = 0; // don't automatically show the last time step - -// CORE - -p_Leg_1_L_0=newp; Point(newp) = {-width_Core/2., 0, 0, c_Core}; -p_Leg_1_R_0=newp; Point(newp) = {-width_Core/2.+width_Core_Leg, 0, 0, c_Core}; - -p_Leg_1_L_1=newp; Point(newp) = {-width_Core/2., height_Core/2., 0, c_Core}; -p_Leg_1_R_1=newp; Point(newp) = {-width_Core/2.+width_Core_Leg, height_Core/2.-width_Core_Leg, 0, c_Core}; - - -p_Leg_2_L_0=newp; Point(newp) = {width_Core/2.-width_Core_Leg, 0, 0, c_Core}; -p_Leg_2_R_0=newp; Point(newp) = {width_Core/2., 0, 0, c_Core}; - -p_Leg_2_L_1=newp; Point(newp) = {width_Core/2.-width_Core_Leg, height_Core/2.-width_Core_Leg, 0, c_Core}; -p_Leg_2_R_1=newp; Point(newp) = {width_Core/2., height_Core/2., 0, c_Core}; - - -l_Core_In[]={}; -l_Core_In[]+=newl; Line(newl) = {p_Leg_1_R_0, p_Leg_1_R_1}; -l_Core_In[]+=newl; Line(newl) = {p_Leg_1_R_1, p_Leg_2_L_1}; -l_Core_In[]+=newl; Line(newl) = {p_Leg_2_L_1, p_Leg_2_L_0}; - -l_Core_Out[]={}; -l_Core_Out[]+=newl; Line(newl) = {p_Leg_2_R_0, p_Leg_2_R_1}; -l_Core_Out[]+=newl; Line(newl) = {p_Leg_2_R_1, p_Leg_1_L_1}; -l_Core_Out[]+=newl; Line(newl) = {p_Leg_1_L_1, p_Leg_1_L_0}; - -l_Core_Leg_1_Y0[]={}; -l_Core_Leg_1_Y0[]+=newl; Line(newl) = {p_Leg_1_L_0, p_Leg_1_R_0}; - -l_Core_Leg_2_Y0[]={}; -l_Core_Leg_2_Y0[]+=newl; Line(newl) = {p_Leg_2_L_0, p_Leg_2_R_0}; - - -ll_Core=newll; Line Loop(newll) = {l_Core_In[], l_Core_Leg_2_Y0[], l_Core_Out[], l_Core_Leg_1_Y0[]}; -s_Core=news; Plane Surface(news) = {ll_Core}; - -Physical Surface("CORE", CORE) = {s_Core}; - -// COIL_1_PLUS - -x_[]=Point{p_Leg_1_R_0}; -p_Coil_1_p_int_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_1, 0, 0, c_Coil_1}; -p_Coil_1_p_ext_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_1+width_Coil_1, 0, 0, c_Coil_1}; -p_Coil_1_p_int_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_1, height_Coil_1/2, 0, c_Coil_1}; -p_Coil_1_p_ext_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_1+width_Coil_1, height_Coil_1/2, 0, c_Coil_1}; - -l_Coil_1_p[]={}; -l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_ext_0, p_Coil_1_p_ext_1}; -l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_ext_1, p_Coil_1_p_int_1}; -l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_int_1, p_Coil_1_p_int_0}; - -l_Coil_1_p_Y0[]={}; -l_Coil_1_p_Y0[]+=newl; Line(newl) = {p_Coil_1_p_int_0, p_Coil_1_p_ext_0}; - -ll_Coil_1_p=newll; Line Loop(newll) = {l_Coil_1_p[], l_Coil_1_p_Y0[]}; -s_Coil_1_p=news; Plane Surface(news) = {ll_Coil_1_p}; - -Physical Surface("COIL_1_PLUS", COIL_1_PLUS) = {s_Coil_1_p}; - - -// COIL_1_MINUS - -x_[]=Point{p_Leg_1_L_0}; -p_Coil_1_m_int_0=newp; Point(newp) = {x_[0]-gap_Core_Coil_1, 0, 0, c_Coil_1}; -p_Coil_1_m_ext_0=newp; Point(newp) = {x_[0]-(gap_Core_Coil_1+width_Coil_1), 0, 0, c_Coil_1}; -p_Coil_1_m_int_1=newp; Point(newp) = {x_[0]-gap_Core_Coil_1, height_Coil_1/2, 0, c_Coil_1}; -p_Coil_1_m_ext_1=newp; Point(newp) = {x_[0]-(gap_Core_Coil_1+width_Coil_1), height_Coil_1/2, 0, c_Coil_1}; - -l_Coil_1_m[]={}; -l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_ext_0, p_Coil_1_m_ext_1}; -l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_ext_1, p_Coil_1_m_int_1}; -l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_int_1, p_Coil_1_m_int_0}; - -l_Coil_1_m_Y0[]={}; -l_Coil_1_m_Y0[]+=newl; Line(newl) = {p_Coil_1_m_int_0, p_Coil_1_m_ext_0}; - -ll_Coil_1_m=newll; Line Loop(newll) = {l_Coil_1_m[], l_Coil_1_m_Y0[]}; -s_Coil_1_m=news; Plane Surface(news) = {ll_Coil_1_m}; - -Physical Surface("COIL_1_MINUS", COIL_1_MINUS) = {s_Coil_1_m}; - - -// COIL_2_PLUS - -x_[]=Point{p_Leg_2_R_0}; -p_Coil_2_p_int_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_2, 0, 0, c_Coil_2}; -p_Coil_2_p_ext_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_2+width_Coil_2, 0, 0, c_Coil_2}; -p_Coil_2_p_int_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_2, height_Coil_2/2, 0, c_Coil_2}; -p_Coil_2_p_ext_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_2+width_Coil_2, height_Coil_2/2, 0, c_Coil_2}; - -l_Coil_2_p[]={}; -l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_ext_0, p_Coil_2_p_ext_1}; -l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_ext_1, p_Coil_2_p_int_1}; -l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_int_1, p_Coil_2_p_int_0}; - -l_Coil_2_p_Y0[]={}; -l_Coil_2_p_Y0[]+=newl; Line(newl) = {p_Coil_2_p_int_0, p_Coil_2_p_ext_0}; - -ll_Coil_2_p=newll; Line Loop(newll) = {l_Coil_2_p[], l_Coil_2_p_Y0[]}; -s_Coil_2_p=news; Plane Surface(news) = {ll_Coil_2_p}; - -Physical Surface("COIL_2_PLUS", COIL_2_PLUS) = {s_Coil_2_p}; - - -// COIL_2_MINUS - -x_[]=Point{p_Leg_2_L_0}; -p_Coil_2_m_int_0=newp; Point(newp) = {x_[0]-gap_Core_Coil_2, 0, 0, c_Coil_2}; -p_Coil_2_m_ext_0=newp; Point(newp) = {x_[0]-(gap_Core_Coil_2+width_Coil_2), 0, 0, c_Coil_2}; -p_Coil_2_m_int_1=newp; Point(newp) = {x_[0]-gap_Core_Coil_2, height_Coil_2/2, 0, c_Coil_2}; -p_Coil_2_m_ext_1=newp; Point(newp) = {x_[0]-(gap_Core_Coil_2+width_Coil_2), height_Coil_2/2, 0, c_Coil_2}; - -l_Coil_2_m[]={}; -l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_ext_0, p_Coil_2_m_ext_1}; -l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_ext_1, p_Coil_2_m_int_1}; -l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_int_1, p_Coil_2_m_int_0}; - -l_Coil_2_m_Y0[]={}; -l_Coil_2_m_Y0[]+=newl; Line(newl) = {p_Coil_2_m_int_0, p_Coil_2_m_ext_0}; - -ll_Coil_2_m=newll; Line Loop(newll) = {l_Coil_2_m[], l_Coil_2_m_Y0[]}; -s_Coil_2_m=news; Plane Surface(news) = {ll_Coil_2_m}; - -Physical Surface("COIL_2_MINUS", COIL_2_MINUS) = {s_Coil_2_m}; - - -// AIR_WINDOW - -l_Air_Window_Y0[]={}; -l_Air_Window_Y0[]+=newl; Line(newl) = {p_Leg_1_R_0, p_Coil_1_p_int_0}; -l_Air_Window_Y0[]+=newl; Line(newl) = {p_Coil_1_p_ext_0, p_Coil_2_m_ext_0}; -l_Air_Window_Y0[]+=newl; Line(newl) = {p_Coil_2_m_int_0, p_Leg_2_L_0}; - -ll_Air_Window=newll; Line Loop(newll) = {-l_Core_In[], -l_Coil_1_p[], l_Coil_2_m[], l_Air_Window_Y0[]}; -s_Air_Window=news; Plane Surface(news) = {ll_Air_Window}; - -Physical Surface("AIR_WINDOW", AIR_WINDOW) = {s_Air_Window}; - - -// AIR_EXT - -x_[]=Point{p_Leg_2_R_1}; -p_Air_Ext_1_R_0=newp; Point(newp) = {x_[0]+gap_Core_Box_X, 0, 0, c_Box}; -p_Air_Ext_1_R_1=newp; Point(newp) = {x_[0]+gap_Core_Box_X, x_[1]+gap_Core_Box_Y, 0, c_Box}; - -x_[]=Point{p_Leg_1_L_1}; -p_Air_Ext_1_L_0=newp; Point(newp) = {x_[0]-gap_Core_Box_X, 0, 0, c_Box}; -p_Air_Ext_1_L_1=newp; Point(newp) = {x_[0]-gap_Core_Box_X, x_[1]+gap_Core_Box_Y, 0, c_Box}; - -l_Air_Ext[]={}; -l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_R_0, p_Air_Ext_1_R_1}; -l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_R_1, p_Air_Ext_1_L_1}; -l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_L_1, p_Air_Ext_1_L_0}; - - -l_Air_Ext_Y0[]={}; -l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Leg_2_R_0, p_Coil_2_p_int_0}; -l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Coil_2_p_ext_0, p_Air_Ext_1_R_0}; - -l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Air_Ext_1_L_0, p_Coil_1_m_ext_0}; -l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Coil_1_m_int_0, p_Leg_1_L_0}; - - -ll_Air_Ext=newll; Line Loop(newll) = {-l_Core_Out[], -l_Coil_2_p[], l_Coil_1_m[], l_Air_Ext[], l_Air_Ext_Y0[]}; -s_Air_Ext=news; Plane Surface(news) = {ll_Air_Ext}; - -Physical Surface("AIR_EXT", AIR_EXT) = {s_Air_Ext}; -Physical Line("SUR_AIR_EXT", SUR_AIR_EXT) = {l_Air_Ext[]}; + +Include "transfo_common.pro"; + +Solver.AutoShowLastStep = 0; // don't automatically show the last time step + +// CORE + +p_Leg_1_L_0=newp; Point(newp) = {-width_Core/2., 0, 0, c_Core}; +p_Leg_1_R_0=newp; Point(newp) = {-width_Core/2.+width_Core_Leg, 0, 0, c_Core}; + +p_Leg_1_L_1=newp; Point(newp) = {-width_Core/2., height_Core/2., 0, c_Core}; +p_Leg_1_R_1=newp; Point(newp) = {-width_Core/2.+width_Core_Leg, height_Core/2.-width_Core_Leg, 0, c_Core}; + + +p_Leg_2_L_0=newp; Point(newp) = {width_Core/2.-width_Core_Leg, 0, 0, c_Core}; +p_Leg_2_R_0=newp; Point(newp) = {width_Core/2., 0, 0, c_Core}; + +p_Leg_2_L_1=newp; Point(newp) = {width_Core/2.-width_Core_Leg, height_Core/2.-width_Core_Leg, 0, c_Core}; +p_Leg_2_R_1=newp; Point(newp) = {width_Core/2., height_Core/2., 0, c_Core}; + + +l_Core_In[]={}; +l_Core_In[]+=newl; Line(newl) = {p_Leg_1_R_0, p_Leg_1_R_1}; +l_Core_In[]+=newl; Line(newl) = {p_Leg_1_R_1, p_Leg_2_L_1}; +l_Core_In[]+=newl; Line(newl) = {p_Leg_2_L_1, p_Leg_2_L_0}; + +l_Core_Out[]={}; +l_Core_Out[]+=newl; Line(newl) = {p_Leg_2_R_0, p_Leg_2_R_1}; +l_Core_Out[]+=newl; Line(newl) = {p_Leg_2_R_1, p_Leg_1_L_1}; +l_Core_Out[]+=newl; Line(newl) = {p_Leg_1_L_1, p_Leg_1_L_0}; + +l_Core_Leg_1_Y0[]={}; +l_Core_Leg_1_Y0[]+=newl; Line(newl) = {p_Leg_1_L_0, p_Leg_1_R_0}; + +l_Core_Leg_2_Y0[]={}; +l_Core_Leg_2_Y0[]+=newl; Line(newl) = {p_Leg_2_L_0, p_Leg_2_R_0}; + + +ll_Core=newll; Line Loop(newll) = {l_Core_In[], l_Core_Leg_2_Y0[], l_Core_Out[], l_Core_Leg_1_Y0[]}; +s_Core=news; Plane Surface(news) = {ll_Core}; + +Physical Surface("CORE", CORE) = {s_Core}; + +// COIL_1_PLUS + +x_[]=Point{p_Leg_1_R_0}; +p_Coil_1_p_int_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_1, 0, 0, c_Coil_1}; +p_Coil_1_p_ext_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_1+width_Coil_1, 0, 0, c_Coil_1}; +p_Coil_1_p_int_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_1, height_Coil_1/2, 0, c_Coil_1}; +p_Coil_1_p_ext_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_1+width_Coil_1, height_Coil_1/2, 0, c_Coil_1}; + +l_Coil_1_p[]={}; +l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_ext_0, p_Coil_1_p_ext_1}; +l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_ext_1, p_Coil_1_p_int_1}; +l_Coil_1_p[]+=newl; Line(newl) = {p_Coil_1_p_int_1, p_Coil_1_p_int_0}; + +l_Coil_1_p_Y0[]={}; +l_Coil_1_p_Y0[]+=newl; Line(newl) = {p_Coil_1_p_int_0, p_Coil_1_p_ext_0}; + +ll_Coil_1_p=newll; Line Loop(newll) = {l_Coil_1_p[], l_Coil_1_p_Y0[]}; +s_Coil_1_p=news; Plane Surface(news) = {ll_Coil_1_p}; + +Physical Surface("COIL_1_PLUS", COIL_1_PLUS) = {s_Coil_1_p}; + + +// COIL_1_MINUS + +x_[]=Point{p_Leg_1_L_0}; +p_Coil_1_m_int_0=newp; Point(newp) = {x_[0]-gap_Core_Coil_1, 0, 0, c_Coil_1}; +p_Coil_1_m_ext_0=newp; Point(newp) = {x_[0]-(gap_Core_Coil_1+width_Coil_1), 0, 0, c_Coil_1}; +p_Coil_1_m_int_1=newp; Point(newp) = {x_[0]-gap_Core_Coil_1, height_Coil_1/2, 0, c_Coil_1}; +p_Coil_1_m_ext_1=newp; Point(newp) = {x_[0]-(gap_Core_Coil_1+width_Coil_1), height_Coil_1/2, 0, c_Coil_1}; + +l_Coil_1_m[]={}; +l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_ext_0, p_Coil_1_m_ext_1}; +l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_ext_1, p_Coil_1_m_int_1}; +l_Coil_1_m[]+=newl; Line(newl) = {p_Coil_1_m_int_1, p_Coil_1_m_int_0}; + +l_Coil_1_m_Y0[]={}; +l_Coil_1_m_Y0[]+=newl; Line(newl) = {p_Coil_1_m_int_0, p_Coil_1_m_ext_0}; + +ll_Coil_1_m=newll; Line Loop(newll) = {l_Coil_1_m[], l_Coil_1_m_Y0[]}; +s_Coil_1_m=news; Plane Surface(news) = {ll_Coil_1_m}; + +Physical Surface("COIL_1_MINUS", COIL_1_MINUS) = {s_Coil_1_m}; + + +// COIL_2_PLUS + +x_[]=Point{p_Leg_2_R_0}; +p_Coil_2_p_int_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_2, 0, 0, c_Coil_2}; +p_Coil_2_p_ext_0=newp; Point(newp) = {x_[0]+gap_Core_Coil_2+width_Coil_2, 0, 0, c_Coil_2}; +p_Coil_2_p_int_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_2, height_Coil_2/2, 0, c_Coil_2}; +p_Coil_2_p_ext_1=newp; Point(newp) = {x_[0]+gap_Core_Coil_2+width_Coil_2, height_Coil_2/2, 0, c_Coil_2}; + +l_Coil_2_p[]={}; +l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_ext_0, p_Coil_2_p_ext_1}; +l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_ext_1, p_Coil_2_p_int_1}; +l_Coil_2_p[]+=newl; Line(newl) = {p_Coil_2_p_int_1, p_Coil_2_p_int_0}; + +l_Coil_2_p_Y0[]={}; +l_Coil_2_p_Y0[]+=newl; Line(newl) = {p_Coil_2_p_int_0, p_Coil_2_p_ext_0}; + +ll_Coil_2_p=newll; Line Loop(newll) = {l_Coil_2_p[], l_Coil_2_p_Y0[]}; +s_Coil_2_p=news; Plane Surface(news) = {ll_Coil_2_p}; + +Physical Surface("COIL_2_PLUS", COIL_2_PLUS) = {s_Coil_2_p}; + + +// COIL_2_MINUS + +x_[]=Point{p_Leg_2_L_0}; +p_Coil_2_m_int_0=newp; Point(newp) = {x_[0]-gap_Core_Coil_2, 0, 0, c_Coil_2}; +p_Coil_2_m_ext_0=newp; Point(newp) = {x_[0]-(gap_Core_Coil_2+width_Coil_2), 0, 0, c_Coil_2}; +p_Coil_2_m_int_1=newp; Point(newp) = {x_[0]-gap_Core_Coil_2, height_Coil_2/2, 0, c_Coil_2}; +p_Coil_2_m_ext_1=newp; Point(newp) = {x_[0]-(gap_Core_Coil_2+width_Coil_2), height_Coil_2/2, 0, c_Coil_2}; + +l_Coil_2_m[]={}; +l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_ext_0, p_Coil_2_m_ext_1}; +l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_ext_1, p_Coil_2_m_int_1}; +l_Coil_2_m[]+=newl; Line(newl) = {p_Coil_2_m_int_1, p_Coil_2_m_int_0}; + +l_Coil_2_m_Y0[]={}; +l_Coil_2_m_Y0[]+=newl; Line(newl) = {p_Coil_2_m_int_0, p_Coil_2_m_ext_0}; + +ll_Coil_2_m=newll; Line Loop(newll) = {l_Coil_2_m[], l_Coil_2_m_Y0[]}; +s_Coil_2_m=news; Plane Surface(news) = {ll_Coil_2_m}; + +Physical Surface("COIL_2_MINUS", COIL_2_MINUS) = {s_Coil_2_m}; + + +// AIR_WINDOW + +l_Air_Window_Y0[]={}; +l_Air_Window_Y0[]+=newl; Line(newl) = {p_Leg_1_R_0, p_Coil_1_p_int_0}; +l_Air_Window_Y0[]+=newl; Line(newl) = {p_Coil_1_p_ext_0, p_Coil_2_m_ext_0}; +l_Air_Window_Y0[]+=newl; Line(newl) = {p_Coil_2_m_int_0, p_Leg_2_L_0}; + +ll_Air_Window=newll; Line Loop(newll) = {-l_Core_In[], -l_Coil_1_p[], l_Coil_2_m[], l_Air_Window_Y0[]}; +s_Air_Window=news; Plane Surface(news) = {ll_Air_Window}; + +Physical Surface("AIR_WINDOW", AIR_WINDOW) = {s_Air_Window}; + + +// AIR_EXT + +x_[]=Point{p_Leg_2_R_1}; +p_Air_Ext_1_R_0=newp; Point(newp) = {x_[0]+gap_Core_Box_X, 0, 0, c_Box}; +p_Air_Ext_1_R_1=newp; Point(newp) = {x_[0]+gap_Core_Box_X, x_[1]+gap_Core_Box_Y, 0, c_Box}; + +x_[]=Point{p_Leg_1_L_1}; +p_Air_Ext_1_L_0=newp; Point(newp) = {x_[0]-gap_Core_Box_X, 0, 0, c_Box}; +p_Air_Ext_1_L_1=newp; Point(newp) = {x_[0]-gap_Core_Box_X, x_[1]+gap_Core_Box_Y, 0, c_Box}; + +l_Air_Ext[]={}; +l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_R_0, p_Air_Ext_1_R_1}; +l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_R_1, p_Air_Ext_1_L_1}; +l_Air_Ext[]+=newl; Line(newl) = {p_Air_Ext_1_L_1, p_Air_Ext_1_L_0}; + + +l_Air_Ext_Y0[]={}; +l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Leg_2_R_0, p_Coil_2_p_int_0}; +l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Coil_2_p_ext_0, p_Air_Ext_1_R_0}; + +l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Air_Ext_1_L_0, p_Coil_1_m_ext_0}; +l_Air_Ext_Y0[]+=newl; Line(newl) = {p_Coil_1_m_int_0, p_Leg_1_L_0}; + + +ll_Air_Ext=newll; Line Loop(newll) = {-l_Core_Out[], -l_Coil_2_p[], l_Coil_1_m[], l_Air_Ext[], l_Air_Ext_Y0[]}; +s_Air_Ext=news; Plane Surface(news) = {ll_Air_Ext}; + +Physical Surface("AIR_EXT", AIR_EXT) = {s_Air_Ext}; +Physical Line("SUR_AIR_EXT", SUR_AIR_EXT) = {l_Air_Ext[]}; diff --git a/Magnetodynamics/transfo.pro b/Magnetodynamics/transfo.pro index 0feabec..17ae2a6 100644 --- a/Magnetodynamics/transfo.pro +++ b/Magnetodynamics/transfo.pro @@ -1,259 +1,259 @@ -/* ------------------------------------------------------------------- - Tutorial 7b : magnetodyamic model of a single-phase transformer - - Features: - - Use of a generic template formulation library - - Frequency- and time-domain dynamic solutions - - Circuit coupling used as a black-box (see Tutorial 8 for details) - - To compute the solution in a terminal: - getdp transfo -solve MagDyn_a_2D -pos Map_a - - To compute the solution interactively from the Gmsh GUI: - File > Open > transfo.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -Include "transfo_common.pro"; - -DefineConstant[ - type_Conds = {2, Choices{1 = "Massive", 2 = "Coil"}, Highlight "Blue", - Name "Parameters/01Conductor type"} - type_Source = {2, Choices{1 = "Current", 2 = "Voltage"}, Highlight "Blue", - Name "Parameters/02Source type"} - type_Analysis = {1, Choices{1 = "Frequency-domain", 2 = "Time-domain"}, Highlight "Blue", - Name "Parameters/03Analysis type"} - Freq = {50, Min 0, Max 1e3, Step 1, - Name "Parameters/Frequency"} -]; - -Group { - /* Abstract regions that will be used in the "Lib_MagStaDyn_av_2D_Cir.pro" - template file included below; the regions are first intialized as empty, - before being filled with physical groups */ - - Vol_CC_Mag = Region[{}]; // Non-conducting regions - Vol_C_Mag = Region[{}]; // Massive conductors - Vol_S_Mag = Region[{}]; // Stranded conductors, i.e., coils - - // air physical groups - Air = Region[{AIR_WINDOW, AIR_EXT}]; - Vol_CC_Mag += Region[Air]; - - // exterior boundary - Sur_Air_Ext = Region[{SUR_AIR_EXT}]; - - // magnetic core of the transformer, assumed to be non-conducting - Core = Region[CORE]; - Vol_CC_Mag += Region[Core]; - - Coil_1_P = Region[COIL_1_PLUS]; - Coil_1_M = Region[COIL_1_MINUS]; - Coil_1 = Region[{Coil_1_P, Coil_1_M}]; - - Coil_2_P = Region[COIL_2_PLUS]; - Coil_2_M = Region[COIL_2_MINUS]; - Coil_2 = Region[{Coil_2_P, Coil_2_M}]; - - Coils = Region[{Coil_1, Coil_2}]; - - If (type_Conds == 1) - Vol_C_Mag += Region[{Coils}]; - ElseIf (type_Conds == 2) - Vol_S_Mag += Region[{Coils}]; - Vol_CC_Mag += Region[{Coils}]; - EndIf -} - - -Function { - mu0 = 4e-7*Pi; - - mu[Air] = 1 * mu0; - - mur_Core = 100; - mu[Core] = mur_Core * mu0; - - mu[Coils] = 1 * mu0; - sigma[Coils] = 1e7; - - // For a correct definition of the voltage - CoefGeo = thickness_Core; - - // To be defined separately for each coil portion - Sc[Coil_1_P] = SurfaceArea[]; - SignBranch[Coil_1_P] = 1; // To fix the convention of positive current (1: - // along Oz, -1: along -Oz) - - Sc[Coil_1_M] = SurfaceArea[]; - SignBranch[Coil_1_M] = -1; - - Sc[Coil_2_P] = SurfaceArea[]; - SignBranch[Coil_2_P] = 1; - - Sc[Coil_2_M] = SurfaceArea[]; - SignBranch[Coil_2_M] = -1; - - // Number of turns (same for PLUS and MINUS portions) (half values because - // half coils are defined) - Ns[Coil_1] = 1; - Ns[Coil_2] = 1; - - // Global definitions (nothing to change): - - // Current density in each coil portion for a unit current (will be multiplied - // by the actual total current in the coil) - js0[Coils] = Ns[]/Sc[] * Vector[0,0,SignBranch[]]; - CoefGeos[Coils] = SignBranch[] * CoefGeo; - - // The reluctivity will be used - nu[] = 1/mu[]; -} - -If(type_Analysis == 1) - Flag_FrequencyDomain = 1; -Else - Flag_FrequencyDomain = 0; -EndIf - -If (type_Source == 1) // current - - Flag_CircuitCoupling = 0; - -ElseIf (type_Source == 2) // voltage - - // PLUS and MINUS coil portions to be connected in series, with applied - // voltage on the resulting branch - Flag_CircuitCoupling = 1; - - // Here is the definition of the circuits on primary and secondary sides: - Group { - // Empty Groups to be filled - Resistance_Cir = Region[{}]; - Inductance_Cir = Region[{}] ; - Capacitance_Cir = Region[{}] ; - SourceV_Cir = Region[{}]; // Voltage sources - SourceI_Cir = Region[{}]; // Current sources - - // Primary side - E_in = Region[10001]; // arbitrary region number (not linked to the mesh) - SourceV_Cir += Region[{E_in}]; - - // Secondary side - R_out = Region[10101]; // arbitrary region number (not linked to the mesh) - Resistance_Cir += Region[{R_out}]; - } - - Function { - deg = Pi/180; - // Input RMS voltage (half of the voltage because of symmetry; half coils - // are defined) - val_E_in = 1.; - phase_E_in = 90 *deg; // Phase in radian (from phase in degree) - // High value for an open-circuit test; Low value for a short-circuit test; - // any value in-between for any charge - Resistance[R_out] = 1e6; - } - - Constraint { - - { Name Current_Cir ; - Case { - } - } - - { Name Voltage_Cir ; - Case { - { Region E_in; Value val_E_in; TimeFunction F_Cos_wt_p[]{2*Pi*Freq, phase_E_in}; } - } - } - - { Name ElectricalCircuit ; Type Network ; - Case Circuit_1 { - // PLUS and MINUS coil portions to be connected in series, together with - // E_in (an additional resistor should be defined to represent the - // Coil_1 end-winding (not considered in the 2D model)) - { Region E_in; Branch {1,2}; } - - { Region Coil_1_P; Branch {2,3} ; } - { Region Coil_1_M; Branch {3,1} ; } - } - Case Circuit_2 { - // PLUS and MINUS coil portions to be connected in series, together with - // R_out (an additional resistor should be defined to represent the - // Coil_2 end-winding (not considered in the 2D model)) - { Region R_out; Branch {1,2}; } - - { Region Coil_2_P; Branch {2,3} ; } - { Region Coil_2_M; Branch {3,1} ; } - } - } - - } - -EndIf - -Constraint { - { Name MagneticVectorPotential_2D; - Case { - { Region Sur_Air_Ext; Value 0; } - } - } - { Name Current_2D; - Case { - If (type_Source == 1) - // Current in each coil (same for PLUS and MINUS portions) - { Region Coil_1; Value 1; TimeFunction F_Sin_wt_p[]{2*Pi*Freq, 0}; } - { Region Coil_2; Value 0; } - EndIf - } - } - { Name Voltage_2D; - Case { - } - } -} - -Include "Lib_MagStaDyn_av_2D_Cir.pro"; - -PostOperation { - { Name Map_a; NameOfPostProcessing MagDyn_a_2D; - Operation { - Print[ j, OnElementsOf Region[{Vol_C_Mag, Vol_S_Mag}], Format Gmsh, File "j.pos" ]; - Print[ b, OnElementsOf Vol_Mag, Format Gmsh, File "b.pos" ]; - Print[ az, OnElementsOf Vol_Mag, Format Gmsh, File "az.pos" ]; - - If (type_Source == 1) // current - // In text file UI.txt: voltage and current for each coil portion (note - // that the voltage is not equally distributed in PLUS and MINUS - // portions, which is the reason why we must apply the total voltage - // through a circuit -> type_Source == 2) - Echo[ "Coil_1_P", Format Table, File "UI.txt" ]; - Print[ U, OnRegion Coil_1_P, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion Coil_1_P, Format FrequencyTable, File > "UI.txt"]; - Echo[ "Coil_1_M", Format Table, File > "UI.txt" ]; - Print[ U, OnRegion Coil_1_M, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion Coil_1_M, Format FrequencyTable, File > "UI.txt"]; - - Echo[ "Coil_2_P", Format Table, File > "UI.txt" ]; - Print[ U, OnRegion Coil_2_P, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion Coil_2_P, Format FrequencyTable, File > "UI.txt"]; - Echo[ "Coil_2_M", Format Table, File > "UI.txt" ]; - Print[ U, OnRegion Coil_2_M, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion Coil_2_M, Format FrequencyTable, File > "UI.txt"]; - - ElseIf (type_Source == 2) - // In text file UI.txt: voltage and current of the primary coil (from E_in) - // (real and imaginary parts!) - Echo[ "E_in", Format Table, File "UI.txt" ]; - Print[ U, OnRegion E_in, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion E_in, Format FrequencyTable, File > "UI.txt"]; - - // In text file UI.txt: voltage and current of the secondary coil (from R_out) - Echo[ "R_out", Format Table, File > "UI.txt" ]; - Print[ U, OnRegion R_out, Format FrequencyTable, File > "UI.txt" ]; - Print[ I, OnRegion R_out, Format FrequencyTable, File > "UI.txt"]; - EndIf - } - } -} +/* ------------------------------------------------------------------- + Tutorial 7b : magnetodyamic model of a single-phase transformer + + Features: + - Use of a generic template formulation library + - Frequency- and time-domain dynamic solutions + - Circuit coupling used as a black-box (see Tutorial 8 for details) + + To compute the solution in a terminal: + getdp transfo -solve MagDyn_a_2D -pos Map_a + + To compute the solution interactively from the Gmsh GUI: + File > Open > transfo.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +Include "transfo_common.pro"; + +DefineConstant[ + type_Conds = {2, Choices{1 = "Massive", 2 = "Coil"}, Highlight "Blue", + Name "Parameters/01Conductor type"} + type_Source = {2, Choices{1 = "Current", 2 = "Voltage"}, Highlight "Blue", + Name "Parameters/02Source type"} + type_Analysis = {1, Choices{1 = "Frequency-domain", 2 = "Time-domain"}, Highlight "Blue", + Name "Parameters/03Analysis type"} + Freq = {50, Min 0, Max 1e3, Step 1, + Name "Parameters/Frequency"} +]; + +Group { + /* Abstract regions that will be used in the "Lib_MagStaDyn_av_2D_Cir.pro" + template file included below; the regions are first intialized as empty, + before being filled with physical groups */ + + Vol_CC_Mag = Region[{}]; // Non-conducting regions + Vol_C_Mag = Region[{}]; // Massive conductors + Vol_S_Mag = Region[{}]; // Stranded conductors, i.e., coils + + // air physical groups + Air = Region[{AIR_WINDOW, AIR_EXT}]; + Vol_CC_Mag += Region[Air]; + + // exterior boundary + Sur_Air_Ext = Region[{SUR_AIR_EXT}]; + + // magnetic core of the transformer, assumed to be non-conducting + Core = Region[CORE]; + Vol_CC_Mag += Region[Core]; + + Coil_1_P = Region[COIL_1_PLUS]; + Coil_1_M = Region[COIL_1_MINUS]; + Coil_1 = Region[{Coil_1_P, Coil_1_M}]; + + Coil_2_P = Region[COIL_2_PLUS]; + Coil_2_M = Region[COIL_2_MINUS]; + Coil_2 = Region[{Coil_2_P, Coil_2_M}]; + + Coils = Region[{Coil_1, Coil_2}]; + + If (type_Conds == 1) + Vol_C_Mag += Region[{Coils}]; + ElseIf (type_Conds == 2) + Vol_S_Mag += Region[{Coils}]; + Vol_CC_Mag += Region[{Coils}]; + EndIf +} + + +Function { + mu0 = 4e-7*Pi; + + mu[Air] = 1 * mu0; + + mur_Core = 100; + mu[Core] = mur_Core * mu0; + + mu[Coils] = 1 * mu0; + sigma[Coils] = 1e7; + + // For a correct definition of the voltage + CoefGeo = thickness_Core; + + // To be defined separately for each coil portion + Sc[Coil_1_P] = SurfaceArea[]; + SignBranch[Coil_1_P] = 1; // To fix the convention of positive current (1: + // along Oz, -1: along -Oz) + + Sc[Coil_1_M] = SurfaceArea[]; + SignBranch[Coil_1_M] = -1; + + Sc[Coil_2_P] = SurfaceArea[]; + SignBranch[Coil_2_P] = 1; + + Sc[Coil_2_M] = SurfaceArea[]; + SignBranch[Coil_2_M] = -1; + + // Number of turns (same for PLUS and MINUS portions) (half values because + // half coils are defined) + Ns[Coil_1] = 1; + Ns[Coil_2] = 1; + + // Global definitions (nothing to change): + + // Current density in each coil portion for a unit current (will be multiplied + // by the actual total current in the coil) + js0[Coils] = Ns[]/Sc[] * Vector[0,0,SignBranch[]]; + CoefGeos[Coils] = SignBranch[] * CoefGeo; + + // The reluctivity will be used + nu[] = 1/mu[]; +} + +If(type_Analysis == 1) + Flag_FrequencyDomain = 1; +Else + Flag_FrequencyDomain = 0; +EndIf + +If (type_Source == 1) // current + + Flag_CircuitCoupling = 0; + +ElseIf (type_Source == 2) // voltage + + // PLUS and MINUS coil portions to be connected in series, with applied + // voltage on the resulting branch + Flag_CircuitCoupling = 1; + + // Here is the definition of the circuits on primary and secondary sides: + Group { + // Empty Groups to be filled + Resistance_Cir = Region[{}]; + Inductance_Cir = Region[{}] ; + Capacitance_Cir = Region[{}] ; + SourceV_Cir = Region[{}]; // Voltage sources + SourceI_Cir = Region[{}]; // Current sources + + // Primary side + E_in = Region[10001]; // arbitrary region number (not linked to the mesh) + SourceV_Cir += Region[{E_in}]; + + // Secondary side + R_out = Region[10101]; // arbitrary region number (not linked to the mesh) + Resistance_Cir += Region[{R_out}]; + } + + Function { + deg = Pi/180; + // Input RMS voltage (half of the voltage because of symmetry; half coils + // are defined) + val_E_in = 1.; + phase_E_in = 90 *deg; // Phase in radian (from phase in degree) + // High value for an open-circuit test; Low value for a short-circuit test; + // any value in-between for any charge + Resistance[R_out] = 1e6; + } + + Constraint { + + { Name Current_Cir ; + Case { + } + } + + { Name Voltage_Cir ; + Case { + { Region E_in; Value val_E_in; TimeFunction F_Cos_wt_p[]{2*Pi*Freq, phase_E_in}; } + } + } + + { Name ElectricalCircuit ; Type Network ; + Case Circuit_1 { + // PLUS and MINUS coil portions to be connected in series, together with + // E_in (an additional resistor should be defined to represent the + // Coil_1 end-winding (not considered in the 2D model)) + { Region E_in; Branch {1,2}; } + + { Region Coil_1_P; Branch {2,3} ; } + { Region Coil_1_M; Branch {3,1} ; } + } + Case Circuit_2 { + // PLUS and MINUS coil portions to be connected in series, together with + // R_out (an additional resistor should be defined to represent the + // Coil_2 end-winding (not considered in the 2D model)) + { Region R_out; Branch {1,2}; } + + { Region Coil_2_P; Branch {2,3} ; } + { Region Coil_2_M; Branch {3,1} ; } + } + } + + } + +EndIf + +Constraint { + { Name MagneticVectorPotential_2D; + Case { + { Region Sur_Air_Ext; Value 0; } + } + } + { Name Current_2D; + Case { + If (type_Source == 1) + // Current in each coil (same for PLUS and MINUS portions) + { Region Coil_1; Value 1; TimeFunction F_Sin_wt_p[]{2*Pi*Freq, 0}; } + { Region Coil_2; Value 0; } + EndIf + } + } + { Name Voltage_2D; + Case { + } + } +} + +Include "Lib_MagStaDyn_av_2D_Cir.pro"; + +PostOperation { + { Name Map_a; NameOfPostProcessing MagDyn_a_2D; + Operation { + Print[ j, OnElementsOf Region[{Vol_C_Mag, Vol_S_Mag}], Format Gmsh, File "j.pos" ]; + Print[ b, OnElementsOf Vol_Mag, Format Gmsh, File "b.pos" ]; + Print[ az, OnElementsOf Vol_Mag, Format Gmsh, File "az.pos" ]; + + If (type_Source == 1) // current + // In text file UI.txt: voltage and current for each coil portion (note + // that the voltage is not equally distributed in PLUS and MINUS + // portions, which is the reason why we must apply the total voltage + // through a circuit -> type_Source == 2) + Echo[ "Coil_1_P", Format Table, File "UI.txt" ]; + Print[ U, OnRegion Coil_1_P, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion Coil_1_P, Format FrequencyTable, File > "UI.txt"]; + Echo[ "Coil_1_M", Format Table, File > "UI.txt" ]; + Print[ U, OnRegion Coil_1_M, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion Coil_1_M, Format FrequencyTable, File > "UI.txt"]; + + Echo[ "Coil_2_P", Format Table, File > "UI.txt" ]; + Print[ U, OnRegion Coil_2_P, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion Coil_2_P, Format FrequencyTable, File > "UI.txt"]; + Echo[ "Coil_2_M", Format Table, File > "UI.txt" ]; + Print[ U, OnRegion Coil_2_M, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion Coil_2_M, Format FrequencyTable, File > "UI.txt"]; + + ElseIf (type_Source == 2) + // In text file UI.txt: voltage and current of the primary coil (from E_in) + // (real and imaginary parts!) + Echo[ "E_in", Format Table, File "UI.txt" ]; + Print[ U, OnRegion E_in, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion E_in, Format FrequencyTable, File > "UI.txt"]; + + // In text file UI.txt: voltage and current of the secondary coil (from R_out) + Echo[ "R_out", Format Table, File > "UI.txt" ]; + Print[ U, OnRegion R_out, Format FrequencyTable, File > "UI.txt" ]; + Print[ I, OnRegion R_out, Format FrequencyTable, File > "UI.txt"]; + EndIf + } + } +} diff --git a/Magnetodynamics/transfo_common.pro b/Magnetodynamics/transfo_common.pro index 53034cc..a116935 100644 --- a/Magnetodynamics/transfo_common.pro +++ b/Magnetodynamics/transfo_common.pro @@ -1,49 +1,49 @@ - -// Dimensions - -width_Core = 1.; -height_Core = 1.; - -// Thickness along Oz (to be considered for a correct definition of voltage) -thickness_Core = 1.; - -width_Window = 0.5; -height_Window = 0.5; - -width_Core_Leg = (width_Core-width_Window)/2.; - -width_Coil_1 = 0.10; -height_Coil_1 = 0.25; -gap_Core_Coil_1 = 0.05; - -width_Coil_2 = 0.10; -height_Coil_2 = 0.25; -gap_Core_Coil_2 = 0.05; - -gap_Core_Box_X = 1.; -gap_Core_Box_Y = 1.; - -// Characteristic lenghts (for mesh sizes) - -s = 1; - -c_Core = width_Core_Leg/10. *s; - -c_Coil_1 = height_Coil_1/2/5 *s; -c_Coil_2 = height_Coil_2/2/5 *s; - -c_Box = gap_Core_Box_X/6. *s; - -// Physical regions - -AIR_EXT = 1001; -SUR_AIR_EXT = 1002; -AIR_WINDOW = 1011; - -CORE = 1050; - -COIL_1_PLUS = 1101; -COIL_1_MINUS = 1102; - -COIL_2_PLUS = 1201; -COIL_2_MINUS = 1202; + +// Dimensions + +width_Core = 1.; +height_Core = 1.; + +// Thickness along Oz (to be considered for a correct definition of voltage) +thickness_Core = 1.; + +width_Window = 0.5; +height_Window = 0.5; + +width_Core_Leg = (width_Core-width_Window)/2.; + +width_Coil_1 = 0.10; +height_Coil_1 = 0.25; +gap_Core_Coil_1 = 0.05; + +width_Coil_2 = 0.10; +height_Coil_2 = 0.25; +gap_Core_Coil_2 = 0.05; + +gap_Core_Box_X = 1.; +gap_Core_Box_Y = 1.; + +// Characteristic lenghts (for mesh sizes) + +s = 1; + +c_Core = width_Core_Leg/10. *s; + +c_Coil_1 = height_Coil_1/2/5 *s; +c_Coil_2 = height_Coil_2/2/5 *s; + +c_Box = gap_Core_Box_X/6. *s; + +// Physical regions + +AIR_EXT = 1001; +SUR_AIR_EXT = 1002; +AIR_WINDOW = 1011; + +CORE = 1050; + +COIL_1_PLUS = 1101; +COIL_1_MINUS = 1102; + +COIL_2_PLUS = 1201; +COIL_2_MINUS = 1202; diff --git a/Magnetostatics/electromagnet.geo b/Magnetostatics/electromagnet.geo index b24c084..7bd410c 100644 --- a/Magnetostatics/electromagnet.geo +++ b/Magnetostatics/electromagnet.geo @@ -1,54 +1,54 @@ -/* ------------------------------------------------------------------- - File "electromagnet.geo" - - This file is the geometrical description used by GMSH to produce - the file "electromagnet.msh". - ------------------------------------------------------------------- */ - -dxCore = 50.e-3; dyCore = 100.e-3; -xInd = 75.e-3; dxInd = 25.e-3; dyInd = 50.e-3; - -Include "electromagnet_common.pro"; - -s = DefineNumber[1, Name "Model parameters/Global mesh size", - Help "Reduce for finer mesh"]; -p0 = 12.e-3 *s; -pCorex = 4.e-3 *s; pCorey0 = 8.e-3 *s; pCorey = 4.e-3 *s; -pIndx = 5.e-3 *s; pIndy = 5.e-3 *s; -pInt = 12.5e-3*s; pExt = 12.5e-3*s; - -Point(1) = {0,0,0,p0}; -Point(2) = {dxCore,0,0,pCorex}; -Point(3) = {dxCore,dyCore,0,pCorey}; -Point(4) = {0,dyCore,0,pCorey0}; -Point(5) = {xInd,0,0,pIndx}; -Point(6) = {xInd+dxInd,0,0,pIndx}; -Point(7) = {xInd+dxInd,dyInd,0,pIndy}; -Point(8) = {xInd,dyInd,0,pIndy}; -Point(9) = {rInt,0,0,pInt}; -Point(10) = {rExt,0,0,pExt}; -Point(11) = {0,rInt,0,pInt}; -Point(12) = {0,rExt,0,pExt}; - -Line(1) = {1,2}; Line(2) = {2,5}; Line(3) = {5,6}; -Line(4) = {6,9}; Line(5) = {9,10}; Line(6) = {1,4}; -Line(7) = {4,11}; Line(8) = {11,12}; Line(9) = {2,3}; -Line(10) = {3,4}; Line(11) = {6,7}; Line(12) = {7,8}; -Line(13) = {8,5}; - -Circle(14) = {9,1,11}; Circle(15) = {10,1,12}; - -Line Loop(16) = {-6,1,9,10}; Plane Surface(17) = {16}; -Line Loop(18) = {11,12,13,3}; Plane Surface(19) = {18}; -Line Loop(20) = {7,-14,-4,11,12,13,-2,9,10}; Plane Surface(21) = {-20}; // "-" for orientation -Line Loop(22) = {8,-15,-5,14}; Plane Surface(23) = {-22}; - -Physical Surface(101) = {21}; /* Air */ -Physical Surface(102) = {17}; /* Core */ -Physical Surface(103) = {19}; /* Ind */ -Physical Surface(111) = {23}; /* AirInf */ - -Physical Line(1100) = {1,2,3,4,5}; /* Surface ht = 0 */ -Physical Line(1101) = {6,7,8}; /* Surface bn = 0 */ -Physical Line(1102) = {15}; /* Surface Inf */ - +/* ------------------------------------------------------------------- + File "electromagnet.geo" + + This file is the geometrical description used by GMSH to produce + the file "electromagnet.msh". + ------------------------------------------------------------------- */ + +dxCore = 50.e-3; dyCore = 100.e-3; +xInd = 75.e-3; dxInd = 25.e-3; dyInd = 50.e-3; + +Include "electromagnet_common.pro"; + +s = DefineNumber[1, Name "Model parameters/Global mesh size", + Help "Reduce for finer mesh"]; +p0 = 12.e-3 *s; +pCorex = 4.e-3 *s; pCorey0 = 8.e-3 *s; pCorey = 4.e-3 *s; +pIndx = 5.e-3 *s; pIndy = 5.e-3 *s; +pInt = 12.5e-3*s; pExt = 12.5e-3*s; + +Point(1) = {0,0,0,p0}; +Point(2) = {dxCore,0,0,pCorex}; +Point(3) = {dxCore,dyCore,0,pCorey}; +Point(4) = {0,dyCore,0,pCorey0}; +Point(5) = {xInd,0,0,pIndx}; +Point(6) = {xInd+dxInd,0,0,pIndx}; +Point(7) = {xInd+dxInd,dyInd,0,pIndy}; +Point(8) = {xInd,dyInd,0,pIndy}; +Point(9) = {rInt,0,0,pInt}; +Point(10) = {rExt,0,0,pExt}; +Point(11) = {0,rInt,0,pInt}; +Point(12) = {0,rExt,0,pExt}; + +Line(1) = {1,2}; Line(2) = {2,5}; Line(3) = {5,6}; +Line(4) = {6,9}; Line(5) = {9,10}; Line(6) = {1,4}; +Line(7) = {4,11}; Line(8) = {11,12}; Line(9) = {2,3}; +Line(10) = {3,4}; Line(11) = {6,7}; Line(12) = {7,8}; +Line(13) = {8,5}; + +Circle(14) = {9,1,11}; Circle(15) = {10,1,12}; + +Line Loop(16) = {-6,1,9,10}; Plane Surface(17) = {16}; +Line Loop(18) = {11,12,13,3}; Plane Surface(19) = {18}; +Line Loop(20) = {7,-14,-4,11,12,13,-2,9,10}; Plane Surface(21) = {-20}; // "-" for orientation +Line Loop(22) = {8,-15,-5,14}; Plane Surface(23) = {-22}; + +Physical Surface(101) = {21}; /* Air */ +Physical Surface(102) = {17}; /* Core */ +Physical Surface(103) = {19}; /* Ind */ +Physical Surface(111) = {23}; /* AirInf */ + +Physical Line(1100) = {1,2,3,4,5}; /* Surface ht = 0 */ +Physical Line(1101) = {6,7,8}; /* Surface bn = 0 */ +Physical Line(1102) = {15}; /* Surface Inf */ + diff --git a/Magnetostatics/electromagnet.pro b/Magnetostatics/electromagnet.pro index 0e4126c..05bed25 100644 --- a/Magnetostatics/electromagnet.pro +++ b/Magnetostatics/electromagnet.pro @@ -1,305 +1,305 @@ -/* ------------------------------------------------------------------- - Tutorial 2 : magnetostatic field of an electromagnet - - Features: - - Infinite ring geometrical transformation - - Parameters shared by Gmsh and GetDP, and ONELAB parameters - - FunctionSpaces for the 2D vector potential formulation - - To compute the solution in a terminal: - getdp electromagnet -solve MagSta_a - getdp electromagnet -pos Map_a - - To compute the solution interactively from the Gmsh GUI: - File > Open > electromagnet.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* Electromagnetic fields expand to infinity. The corresponding boundary - condition can be imposed rigorously by means of a gometrical transformation - that maps a ring (or shell) of finite elements to the complementary of its - interior. As this is a mere geometric transformation, it is enough in the - model description to attribute a special Jacobian to the ring region - ("AirInf") - see the "Jacobian" section below. With this information, GetDP - is able to deal with the correct transformation of all quantities involved in - the model. - - The special Jacobian "VolSphShell" takes 2 parameters in this case, - "Val_Rint" and "Val_Rext", which represent the inner and outer radii of the - transformed ring region and whose value must match those used in the - geometrical description of the model (.geo file). This is a typical case - where Gmsh and GetDP must consistently share parameter values. To ensure - consistency in all cases, common parameters are defined is a specific file - "electromagnet_common.pro", which is included in both the .geo and .pro file - of the model. - - Besides sharing parameters between Gmsh and GetDP, it is also useful to share - some parameters (not all) with the user of the model, i.e., to make them - editable in the GUI before running the model. Such variables are called - ONELAB variables (because the sharing mechanism between the model and the GUI - uses the ONELAB interface). ONELAB parameters are defined with a - "DefineNumber" statement, which can be invoked in the .geo and .pro files. - - This model computes the static magnetic field produced by a DC current. This - corresponds to a "magnetostatic" physical model, obtained by combining the - time-invariant Maxwell-Ampere equation (curl h = js, with h the magnetic - field and js the source current density) with Gauss' law (Div b = 0, with b - the magnetic flux density) and the magnetic constitutive law (b = mu h, with - mu the magnetic permeability). - - Since Div b = 0, b can be derived from a vector magnetic potential a, such - that b = curl a. Plugging this potential in Maxwell-Ampere's law and using - the constitutive law leads to a vector Poisson equation in terms of the - magnetic vector potential: curl(nu curl a) = js, where nu = 1/mu is - the reluctivity. */ - -Group { - // Physical regions: - Air = Region[ 101 ]; Core = Region[ 102 ]; - Ind = Region[ 103 ]; AirInf = Region[ 111 ]; - - Surface_ht0 = Region[ 1100 ]; - Surface_bn0 = Region[ 1101 ]; - Surface_Inf = Region[ 1102 ]; - - /* Abstract regions : - The purpose of abstract regions is to allow a generic definition of the - FunctionSpace, Formulation and PostProcessing fields with no reference to - model-specific Physical regions. We will show in a later tutorial how - abstract formulations can then be isolated in geometry independent template - files, thanks to an appropriate declaration mechanism (using - DefineConstant[], DefineGroup[] and DefineFunction[]). - - The abstract regions in this model have the following interpretation: - - Vol_Mag : full volume domain - - Vol_S_Mag : region where the current source js is defined - - Vol_Inf_Mag : region where the infinite ring geometric transformation is applied - - Sur_Dir_Mag : part of the boundary with homogenous Dirichlet conditions - - Sur_Neu_Mag : part of the boundary with non-homogeneous Neumann conditions - */ - Vol_Mag = Region[ {Air, AirInf, Core, Ind} ]; - Vol_S_Mag = Region[ Ind ]; - Vol_Inf_Mag = Region[ AirInf ]; - Sur_Dir_Mag = Region[ {Surface_bn0, Surface_Inf} ]; - Sur_Neu_Mag = Region[ {} ]; // empty -} - -/* The weak formulation for this problem is derived in a similar way to the - electrostatic weak formulation from Tutorial 1. The main difference is that - the fields are now vector-valued, and that we have one linear (source) term - in addition to the bilinear term. The weak formulation reads: find a such - that - - (curl(nu curl a), a')_Vol_Mag = (js, a')_Vol_S_Mag - - holds for all test functions a'. After integration by parts it reads: find a - such that - - (nu curl a, curl a')_Vol_Mag + (n x (nu curl a), a')_Bnd_Vol_Mag = (js, a')_Vol_S_Mag - - In this electromagnet model the second (boundary) term vanishes, as there is - either no test function a' (on the Dirichlet boundary), or "n x (nu curl a) = - n x h" is zero (on the homogeneous Neumann boundary). We are thus eventually - looking for functions a such that - - (nu curl a, curl a')_Vol_Mag = (js, a')_Vol_S_Mag - - holds for all a'. */ - -Function { - mu0 = 4.e-7 * Pi; - murCore = DefineNumber[100, Name "Model parameters/Mur core", - Help "Magnetic relative permeability of Core"]; - - nu [ Region[{Air, Ind, AirInf}] ] = 1. / mu0; - nu [ Core ] = 1. / (murCore * mu0); - - Current = DefineNumber[0.01, Name "Model parameters/Current", - Help "Current injected in coil [A]"]; - NbTurns = 1000 ; // number of turns in the coil - js_fct[ Ind ] = -NbTurns*Current/SurfaceArea[]; - /* The minus sign is to have the current in -e_z direction, - so that the magnetic induction field is in +e_y direction */ -} - -Constraint { - { Name Dirichlet_a_Mag; - Case { - { Region Sur_Dir_Mag ; Value 0.; } - } - } - { Name SourceCurrentDensityZ; - Case { - { Region Vol_S_Mag ; Value js_fct[]; } - } - } -} - -/* In the 2D approximation, the magnetic vector potential a and the current - density js are vectors with a z-component only, i.e.: - - a = Vector [ 0, 0, az(x,y) ] - js = Vector [ 0, 0, jsz(x,y) ] - - These vector fields behave differently under derivation and geometrical - transformation though, and GetDP needs this information to perform these - operations correctly. This is reflected in the Type, BasisFunction and Entity - specified in the "Hcurl_a_Mag_2D" FunctionSpace for a ("Perpendicular 1-form" - with "BF_PerpendicularEdge" basis functions associated to nodes of the mesh) - and in the "Hregion_j_Mag_2D" FunctionSpace for js ("Vector" with - "BF_RegionZ" basis functions associated with the region Vol_S_Mag). Without - giving all the details, a is thus node-based, whereas js is region-wise - constant. */ - -Group { - Dom_Hcurl_a_Mag_2D = Region[ {Vol_Mag, Sur_Neu_Mag} ]; -} - -FunctionSpace { - { Name Hcurl_a_Mag_2D; Type Form1P; // Magnetic vector potential a - BasisFunction { - { Name se; NameOfCoef ae; Function BF_PerpendicularEdge; - Support Dom_Hcurl_a_Mag_2D ; Entity NodesOf[ All ]; } - } - Constraint { - { NameOfCoef ae; EntityType NodesOf; - NameOfConstraint Dirichlet_a_Mag; } - } - } - - { Name Hregion_j_Mag_2D; Type Vector; // Electric current density js - BasisFunction { - { Name sr; NameOfCoef jsr; Function BF_RegionZ; - Support Vol_S_Mag; Entity Vol_S_Mag; } - } - Constraint { - { NameOfCoef jsr; EntityType Region; - NameOfConstraint SourceCurrentDensityZ; } - } - } - -} - -Include "electromagnet_common.pro"; -Val_Rint = rInt; Val_Rext = rExt; - -Jacobian { - { Name Vol ; - Case { { Region Vol_Inf_Mag ; - Jacobian VolSphShell {Val_Rint, Val_Rext} ; } - { Region All ; Jacobian Vol ; } - } - } -} - -Integration { - { Name Int ; - Case { { Type Gauss ; - Case { { GeoElement Triangle ; NumberOfPoints 4 ; } - { GeoElement Quadrangle ; NumberOfPoints 4 ; } - } - } - } - } -} - -/* The function space "Hregion_j_Mag_2D" provides one basis function, and hence - one degree of freedom, per physical region in the abstract region - "Vol_S_Mag". The constraint "SourceCurrentDensityZ" fixes all these dofs, so - the FunctionSpace "Hregion_j_Mag_2D" is fully fixed and has no FE unknowns. - One could thus have replaced it by a simple function and the Integral term - below in the weak formulation could have been written as - - Integral { [ Vector[ 0,0,-js_fct[] ] , {a} ]; - In Vol_S_Mag; Jacobian Vol; Integration Int; } - - instead of - - Integral { [ - Dof{js} , {a} ]; - In Vol_S_Mag; Jacobian Vol; Integration Int; } - - The chosen implementation below is however more effeicient as it avoids - evaluating repeatedly the function js_fct[] during assembly. -*/ - -Formulation { - { Name Magnetostatics_a_2D; Type FemEquation; - Quantity { - { Name a ; Type Local; NameOfSpace Hcurl_a_Mag_2D; } - { Name js; Type Local; NameOfSpace Hregion_j_Mag_2D; } - } - Equation { - // all terms on the left-hand side (hence the "-" sign in front of - // Dof{js}): - Integral { [ nu[] * Dof{d a} , {d a} ]; - In Vol_Mag; Jacobian Vol; Integration Int; } - Integral { [ -Dof{js} , {a} ]; - In Vol_S_Mag; Jacobian Vol; Integration Int; } - } - } -} - -Resolution { - { Name MagSta_a; - System { - { Name Sys_Mag; NameOfFormulation Magnetostatics_a_2D; } - } - Operation { - Generate[Sys_Mag]; Solve[Sys_Mag]; SaveSolution[Sys_Mag]; - } - } -} - -PostProcessing { - { Name MagSta_a_2D; NameOfFormulation Magnetostatics_a_2D; - Quantity { - { Name a; - Value { - Term { [ {a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } - } - } - { Name az; - Value { - Term { [ CompZ[{a}] ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } - } - } - { Name b; - Value { - Term { [ {d a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } - } - } - { Name h; - Value { - Term { [ nu[] * {d a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } - } - } - { Name js; - Value { - Term { [ {js} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } - } - } - } - } -} - -e = 1.e-5; -h = 0.02; -p1 = {e,h,0}; -p2 = {0.25-e,h,0}; // horizontal cut through model, just above x-axis. - -PostOperation { - - { Name Map_a; NameOfPostProcessing MagSta_a_2D; - Operation { - Echo[ Str["l=PostProcessing.NbViews-1;", - "View[l].IntervalsType = 1;", - "View[l].NbIso = 40;"], - File "tmp.geo", LastTimeStepOnly] ; - Print[ a, OnElementsOf Dom_Hcurl_a_Mag_2D, File "a.pos" ]; - Print[ js, OnElementsOf Dom_Hcurl_a_Mag_2D, File "js.pos" ]; - Print[ az, OnElementsOf Dom_Hcurl_a_Mag_2D, File "az.pos" ]; - Print[ b, OnElementsOf Dom_Hcurl_a_Mag_2D, File "b.pos" ]; - Print[ b, OnLine{{List[p1]}{List[p2]}} {50}, File "by.pos" ]; - } - } -} +/* ------------------------------------------------------------------- + Tutorial 2 : magnetostatic field of an electromagnet + + Features: + - Infinite ring geometrical transformation + - Parameters shared by Gmsh and GetDP, and ONELAB parameters + - FunctionSpaces for the 2D vector potential formulation + + To compute the solution in a terminal: + getdp electromagnet -solve MagSta_a + getdp electromagnet -pos Map_a + + To compute the solution interactively from the Gmsh GUI: + File > Open > electromagnet.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* Electromagnetic fields expand to infinity. The corresponding boundary + condition can be imposed rigorously by means of a gometrical transformation + that maps a ring (or shell) of finite elements to the complementary of its + interior. As this is a mere geometric transformation, it is enough in the + model description to attribute a special Jacobian to the ring region + ("AirInf") - see the "Jacobian" section below. With this information, GetDP + is able to deal with the correct transformation of all quantities involved in + the model. + + The special Jacobian "VolSphShell" takes 2 parameters in this case, + "Val_Rint" and "Val_Rext", which represent the inner and outer radii of the + transformed ring region and whose value must match those used in the + geometrical description of the model (.geo file). This is a typical case + where Gmsh and GetDP must consistently share parameter values. To ensure + consistency in all cases, common parameters are defined is a specific file + "electromagnet_common.pro", which is included in both the .geo and .pro file + of the model. + + Besides sharing parameters between Gmsh and GetDP, it is also useful to share + some parameters (not all) with the user of the model, i.e., to make them + editable in the GUI before running the model. Such variables are called + ONELAB variables (because the sharing mechanism between the model and the GUI + uses the ONELAB interface). ONELAB parameters are defined with a + "DefineNumber" statement, which can be invoked in the .geo and .pro files. + + This model computes the static magnetic field produced by a DC current. This + corresponds to a "magnetostatic" physical model, obtained by combining the + time-invariant Maxwell-Ampere equation (curl h = js, with h the magnetic + field and js the source current density) with Gauss' law (Div b = 0, with b + the magnetic flux density) and the magnetic constitutive law (b = mu h, with + mu the magnetic permeability). + + Since Div b = 0, b can be derived from a vector magnetic potential a, such + that b = curl a. Plugging this potential in Maxwell-Ampere's law and using + the constitutive law leads to a vector Poisson equation in terms of the + magnetic vector potential: curl(nu curl a) = js, where nu = 1/mu is + the reluctivity. */ + +Group { + // Physical regions: + Air = Region[ 101 ]; Core = Region[ 102 ]; + Ind = Region[ 103 ]; AirInf = Region[ 111 ]; + + Surface_ht0 = Region[ 1100 ]; + Surface_bn0 = Region[ 1101 ]; + Surface_Inf = Region[ 1102 ]; + + /* Abstract regions : + The purpose of abstract regions is to allow a generic definition of the + FunctionSpace, Formulation and PostProcessing fields with no reference to + model-specific Physical regions. We will show in a later tutorial how + abstract formulations can then be isolated in geometry independent template + files, thanks to an appropriate declaration mechanism (using + DefineConstant[], DefineGroup[] and DefineFunction[]). + + The abstract regions in this model have the following interpretation: + - Vol_Mag : full volume domain + - Vol_S_Mag : region where the current source js is defined + - Vol_Inf_Mag : region where the infinite ring geometric transformation is applied + - Sur_Dir_Mag : part of the boundary with homogenous Dirichlet conditions + - Sur_Neu_Mag : part of the boundary with non-homogeneous Neumann conditions + */ + Vol_Mag = Region[ {Air, AirInf, Core, Ind} ]; + Vol_S_Mag = Region[ Ind ]; + Vol_Inf_Mag = Region[ AirInf ]; + Sur_Dir_Mag = Region[ {Surface_bn0, Surface_Inf} ]; + Sur_Neu_Mag = Region[ {} ]; // empty +} + +/* The weak formulation for this problem is derived in a similar way to the + electrostatic weak formulation from Tutorial 1. The main difference is that + the fields are now vector-valued, and that we have one linear (source) term + in addition to the bilinear term. The weak formulation reads: find a such + that + + (curl(nu curl a), a')_Vol_Mag = (js, a')_Vol_S_Mag + + holds for all test functions a'. After integration by parts it reads: find a + such that + + (nu curl a, curl a')_Vol_Mag + (n x (nu curl a), a')_Bnd_Vol_Mag = (js, a')_Vol_S_Mag + + In this electromagnet model the second (boundary) term vanishes, as there is + either no test function a' (on the Dirichlet boundary), or "n x (nu curl a) = + n x h" is zero (on the homogeneous Neumann boundary). We are thus eventually + looking for functions a such that + + (nu curl a, curl a')_Vol_Mag = (js, a')_Vol_S_Mag + + holds for all a'. */ + +Function { + mu0 = 4.e-7 * Pi; + murCore = DefineNumber[100, Name "Model parameters/Mur core", + Help "Magnetic relative permeability of Core"]; + + nu [ Region[{Air, Ind, AirInf}] ] = 1. / mu0; + nu [ Core ] = 1. / (murCore * mu0); + + Current = DefineNumber[0.01, Name "Model parameters/Current", + Help "Current injected in coil [A]"]; + NbTurns = 1000 ; // number of turns in the coil + js_fct[ Ind ] = -NbTurns*Current/SurfaceArea[]; + /* The minus sign is to have the current in -e_z direction, + so that the magnetic induction field is in +e_y direction */ +} + +Constraint { + { Name Dirichlet_a_Mag; + Case { + { Region Sur_Dir_Mag ; Value 0.; } + } + } + { Name SourceCurrentDensityZ; + Case { + { Region Vol_S_Mag ; Value js_fct[]; } + } + } +} + +/* In the 2D approximation, the magnetic vector potential a and the current + density js are vectors with a z-component only, i.e.: + + a = Vector [ 0, 0, az(x,y) ] + js = Vector [ 0, 0, jsz(x,y) ] + + These vector fields behave differently under derivation and geometrical + transformation though, and GetDP needs this information to perform these + operations correctly. This is reflected in the Type, BasisFunction and Entity + specified in the "Hcurl_a_Mag_2D" FunctionSpace for a ("Perpendicular 1-form" + with "BF_PerpendicularEdge" basis functions associated to nodes of the mesh) + and in the "Hregion_j_Mag_2D" FunctionSpace for js ("Vector" with + "BF_RegionZ" basis functions associated with the region Vol_S_Mag). Without + giving all the details, a is thus node-based, whereas js is region-wise + constant. */ + +Group { + Dom_Hcurl_a_Mag_2D = Region[ {Vol_Mag, Sur_Neu_Mag} ]; +} + +FunctionSpace { + { Name Hcurl_a_Mag_2D; Type Form1P; // Magnetic vector potential a + BasisFunction { + { Name se; NameOfCoef ae; Function BF_PerpendicularEdge; + Support Dom_Hcurl_a_Mag_2D ; Entity NodesOf[ All ]; } + } + Constraint { + { NameOfCoef ae; EntityType NodesOf; + NameOfConstraint Dirichlet_a_Mag; } + } + } + + { Name Hregion_j_Mag_2D; Type Vector; // Electric current density js + BasisFunction { + { Name sr; NameOfCoef jsr; Function BF_RegionZ; + Support Vol_S_Mag; Entity Vol_S_Mag; } + } + Constraint { + { NameOfCoef jsr; EntityType Region; + NameOfConstraint SourceCurrentDensityZ; } + } + } + +} + +Include "electromagnet_common.pro"; +Val_Rint = rInt; Val_Rext = rExt; + +Jacobian { + { Name Vol ; + Case { { Region Vol_Inf_Mag ; + Jacobian VolSphShell {Val_Rint, Val_Rext} ; } + { Region All ; Jacobian Vol ; } + } + } +} + +Integration { + { Name Int ; + Case { { Type Gauss ; + Case { { GeoElement Triangle ; NumberOfPoints 4 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } + } + } + } + } +} + +/* The function space "Hregion_j_Mag_2D" provides one basis function, and hence + one degree of freedom, per physical region in the abstract region + "Vol_S_Mag". The constraint "SourceCurrentDensityZ" fixes all these dofs, so + the FunctionSpace "Hregion_j_Mag_2D" is fully fixed and has no FE unknowns. + One could thus have replaced it by a simple function and the Integral term + below in the weak formulation could have been written as + + Integral { [ Vector[ 0,0,-js_fct[] ] , {a} ]; + In Vol_S_Mag; Jacobian Vol; Integration Int; } + + instead of + + Integral { [ - Dof{js} , {a} ]; + In Vol_S_Mag; Jacobian Vol; Integration Int; } + + The chosen implementation below is however more effeicient as it avoids + evaluating repeatedly the function js_fct[] during assembly. +*/ + +Formulation { + { Name Magnetostatics_a_2D; Type FemEquation; + Quantity { + { Name a ; Type Local; NameOfSpace Hcurl_a_Mag_2D; } + { Name js; Type Local; NameOfSpace Hregion_j_Mag_2D; } + } + Equation { + // all terms on the left-hand side (hence the "-" sign in front of + // Dof{js}): + Integral { [ nu[] * Dof{d a} , {d a} ]; + In Vol_Mag; Jacobian Vol; Integration Int; } + Integral { [ -Dof{js} , {a} ]; + In Vol_S_Mag; Jacobian Vol; Integration Int; } + } + } +} + +Resolution { + { Name MagSta_a; + System { + { Name Sys_Mag; NameOfFormulation Magnetostatics_a_2D; } + } + Operation { + Generate[Sys_Mag]; Solve[Sys_Mag]; SaveSolution[Sys_Mag]; + } + } +} + +PostProcessing { + { Name MagSta_a_2D; NameOfFormulation Magnetostatics_a_2D; + Quantity { + { Name a; + Value { + Term { [ {a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } + } + } + { Name az; + Value { + Term { [ CompZ[{a}] ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } + } + } + { Name b; + Value { + Term { [ {d a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } + } + } + { Name h; + Value { + Term { [ nu[] * {d a} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } + } + } + { Name js; + Value { + Term { [ {js} ]; In Dom_Hcurl_a_Mag_2D; Jacobian Vol; } + } + } + } + } +} + +e = 1.e-5; +h = 0.02; +p1 = {e,h,0}; +p2 = {0.25-e,h,0}; // horizontal cut through model, just above x-axis. + +PostOperation { + + { Name Map_a; NameOfPostProcessing MagSta_a_2D; + Operation { + Echo[ Str["l=PostProcessing.NbViews-1;", + "View[l].IntervalsType = 1;", + "View[l].NbIso = 40;"], + File "tmp.geo", LastTimeStepOnly] ; + Print[ a, OnElementsOf Dom_Hcurl_a_Mag_2D, File "a.pos" ]; + Print[ js, OnElementsOf Dom_Hcurl_a_Mag_2D, File "js.pos" ]; + Print[ az, OnElementsOf Dom_Hcurl_a_Mag_2D, File "az.pos" ]; + Print[ b, OnElementsOf Dom_Hcurl_a_Mag_2D, File "b.pos" ]; + Print[ b, OnLine{{List[p1]}{List[p2]}} {50}, File "by.pos" ]; + } + } +} diff --git a/Magnetostatics/electromagnet_common.pro b/Magnetostatics/electromagnet_common.pro index f0dd285..56879cd 100644 --- a/Magnetostatics/electromagnet_common.pro +++ b/Magnetostatics/electromagnet_common.pro @@ -1,4 +1,4 @@ -// Parameters shared by Gmsh and GetDP - -rInt = 200.e-3; -rExt = 250.e-3; +// Parameters shared by Gmsh and GetDP + +rInt = 200.e-3; +rExt = 250.e-3; diff --git a/PotentialFlow/magnus.geo b/PotentialFlow/magnus.geo index 3d477a7..c78c6ac 100644 --- a/PotentialFlow/magnus.geo +++ b/PotentialFlow/magnus.geo @@ -1,71 +1,71 @@ -Include "magnus_common.pro"; - -A = (BoxSize-1)/2.; -B = A; -R = 0.5; -lc = A/10; - - -If( Flag_Object == 0 ) // Cylinder - -lcr = 0.1; -Point(1) = { 2*R, 0.0, 0.0, lcr}; -Point(2) = { R, -R, 0.0, lcr}; -Point(3) = { 0.0, 0.0, 0.0, lcr}; -Point(4) = { R, R, 0.0 , lcr}; -Point(5) = { R, 0.0, 0.0 , lcr}; -Circle(1) = {1,5,2}; -Circle(2) = {2,5,3}; -Circle(3) = {3,5,4}; -Circle(4) = {4,5,1}; - -// Points to be connected with the outer boundary -PtA = 4; -PtB = 2; - -Else // naca airfoil - -lca = 0.03; -Include "nacaAirFoil.geo"; -PtA = 121; -PtB = 81; - -EndIf - -Point(306) = { 0, B, 0, lc}; -Point(307) = { 0,-B, 0, lc}; - -Line(5) = { PtA, 306 }; -Line(6) = { PtB, 307 }; - -Point(308) = {-A,-B, 0, lc}; -Point(309) = {-A, B, 0, lc}; -Point(310) = { A+1, B, 0, lc}; -Point(311) = { A+1,-B, 0, lc}; - -Line( 7) = { 306, 309 }; -Line( 8) = { 309, 308 }; -Line( 9) = { 308, 307 }; -Line(10) = { 307, 311 }; -Line(11) = { 311, 310 }; -Line(12) = { 310, 306 }; - -Line Loop(21) = { 7, 8, 9, -6, 2, 3, 5 }; // aire a gauche -Line Loop(22) = { 10, 11, 12, -5, 4, 1, 6 }; - -Plane Surface(24) = { 21 }; -Plane Surface(25) = { 22 }; - -Physical Surface("Fluid", 2) = { 24, 25 }; -Physical Line("UpStream", 10) = { 8 }; -Physical Line("DownStream", 11) = { 11 }; -Physical Line("Airfoil", 12) = { 1 ... 4 }; -Physical Line("Wake", 13) = { 5 }; - - - -//Line Loop(20) = {1,2,3,4}; -//Plane Surface(23) = {20}; -//Physical Surface("Cylinder", 1) = {23}; -//Physical Line("Outer", 10) = { 7 ... 12 }; - +Include "magnus_common.pro"; + +A = (BoxSize-1)/2.; +B = A; +R = 0.5; +lc = A/10; + + +If( Flag_Object == 0 ) // Cylinder + +lcr = 0.1; +Point(1) = { 2*R, 0.0, 0.0, lcr}; +Point(2) = { R, -R, 0.0, lcr}; +Point(3) = { 0.0, 0.0, 0.0, lcr}; +Point(4) = { R, R, 0.0 , lcr}; +Point(5) = { R, 0.0, 0.0 , lcr}; +Circle(1) = {1,5,2}; +Circle(2) = {2,5,3}; +Circle(3) = {3,5,4}; +Circle(4) = {4,5,1}; + +// Points to be connected with the outer boundary +PtA = 4; +PtB = 2; + +Else // naca airfoil + +lca = 0.03; +Include "nacaAirFoil.geo"; +PtA = 121; +PtB = 81; + +EndIf + +Point(306) = { 0, B, 0, lc}; +Point(307) = { 0,-B, 0, lc}; + +Line(5) = { PtA, 306 }; +Line(6) = { PtB, 307 }; + +Point(308) = {-A,-B, 0, lc}; +Point(309) = {-A, B, 0, lc}; +Point(310) = { A+1, B, 0, lc}; +Point(311) = { A+1,-B, 0, lc}; + +Line( 7) = { 306, 309 }; +Line( 8) = { 309, 308 }; +Line( 9) = { 308, 307 }; +Line(10) = { 307, 311 }; +Line(11) = { 311, 310 }; +Line(12) = { 310, 306 }; + +Line Loop(21) = { 7, 8, 9, -6, 2, 3, 5 }; // aire a gauche +Line Loop(22) = { 10, 11, 12, -5, 4, 1, 6 }; + +Plane Surface(24) = { 21 }; +Plane Surface(25) = { 22 }; + +Physical Surface("Fluid", 2) = { 24, 25 }; +Physical Line("UpStream", 10) = { 8 }; +Physical Line("DownStream", 11) = { 11 }; +Physical Line("Airfoil", 12) = { 1 ... 4 }; +Physical Line("Wake", 13) = { 5 }; + + + +//Line Loop(20) = {1,2,3,4}; +//Plane Surface(23) = {20}; +//Physical Surface("Cylinder", 1) = {23}; +//Physical Line("Outer", 10) = { 7 ... 12 }; + diff --git a/PotentialFlow/magnus.pro b/PotentialFlow/magnus.pro index 77535d0..75c41f0 100644 --- a/PotentialFlow/magnus.pro +++ b/PotentialFlow/magnus.pro @@ -1,431 +1,431 @@ -/* ------------------------------------------------------------------- - Tutorial 6 : Potential flow and Magnus effect - - Features: - - Potential flow, irrotational flow - - Multivalued scalar field - - Lift and Magnus effect, stagnation points - - Run-time variables - - Elementary algorithms in the Resolution section - - Non-linear iteration to achieve Kutta's condition - - To compute the solution in a terminal: - getdp magnus.pro -solve PotentialFlow -pos PotentialFlow - gmsh magnus.geo velocity.pos - - To compute the solution interactively from the Gmsh GUI: - File > Open > magnus.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* This model solves a 2D potential flow around a cylinder or a naca airfoil - placed in a uniform "V_infinity" flow. Potential flows are defined by - - V = grad phi => curl V = 0 - - where the multivalued scalar potential "phi" presents a discontinuity of - magnitude "deltaPhi" across a cut "Sur_Cut". In consequence, the velocity - field "V" is curl-free over the wole domain of analysis "Vol_rho" but its - circulation over any closed curve circling around the object, a quantity - often noted "Gamma" in the literature, gives "deltaPhi" as a result. The - circulation of "V" over closed curves not circling around the object is zero. - - In the GetDP model, the discontinuity "deltaPhi" [m^2/s] is defined as a - global quantity in the Functional space of "phi". The associated (dual) - global quantity is the mass flow density, noted "Dmdt", which has [kg/s] as a - unit. - - Governing equations are - - div ( rho[] grad phi ) = 0 in Vol_rho - rho[] grad phi . n = rho[] Vn = 0 on Sur_Neu - - whereas the uniform velocity field "V_infinity" is imposed by means of - Dirichlet boundary conditions on the upstream and downstream surfaces - "GammaUp" and "GammaDown". - - Momentum equation is decoupled in case of stationary potential flows. The - velocity filed can be solved first, and the pressure is obtained afterwards - by invoking Bernoulli's theorem: - - p = -0.5 * rho[] * SquNorm [ {d phi} ] - - The "Lift" force in "Y" direction is then evaluated either by integrating "p - * CompY[Normal[]]" over the contour of the object, or by the Kutta-Jukowski - theorem - - Lift = - L_z rho[] V_infinity Gamma - - which is a first order approximation of the former. - - "Cylinder" case: - - Either the circulation "deltaPhi" or the mass flow rate "Dmdt" can be - imposed, according to the "Flag_Circ" flag. The Lift is evaluated by both - the integration of pressure and the Kutta-Jukowski approximation. - - "Airfoil" case: - - - If "Flag_Circ == 1", the model works similar to the "Cylinder" case. - - - If "Flag_Circ == 0", the mass flow rate is not directly imposed in this - case. It is determined so that the Kutta condition is verified. This - condition states that the actual value of "Dmdt" is the one for which the - stagnation point (singularity of the velocity field) is located at the - trailing edge of the airfoil,. This is true when the function - - argVTrail[] = ( Atan2[CompY[$1], CompX[$1] ] - Incidence ) / deg ; - - returns zero when evaluated for the velocity at a point "P_edge" close to - the trailing edge of the airfoil. A non linear iteration is thus done by - means of a pseudo-newton scheme, updating the value of the imposed "Dmdt" - until the norm of the residual - - f(V) = argVTrail[ {d phi } ] OnPoint {1.0001,0,0} - - comes below a fixed tolerance. */ - -Include "magnus_common.pro"; - -Group{ - // Physical regions - Fluid = Region[ 2 ]; - GammaUp = Region[ 10 ]; - GammaDown = Region[ 11 ]; - GammaAirf = Region[ 12 ]; - GammaCut = Region[ 13 ]; - - // Abstract regions - Vol_rho = Region[ { Fluid } ]; - Sur_Dir = Region[ { GammaUp, GammaDown } ]; - Sur_Neu = Region[ { GammaAirf } ]; - Sur_Cut = Region[ { GammaCut } ]; -} - -Function{ - rho[] = 1.225; // kg/m^3 - MassFlowRate[] = MassFlowRate; // kg/s - DeltaPhi[] = DeltaPhi; // m^2/s - argVTrail[] = ( Atan2[CompY[$1], CompX[$1] ] - Incidence ) / deg ; -} - -Jacobian { - { Name Vol ; - Case { - { Region All ; Jacobian Vol ; } - } - } - { Name Sur ; - Case { - { Region All ; Jacobian Sur ; } - } - } -} - -Integration { - { Name Int ; - Case { - { Type Gauss ; - Case { - { GeoElement Point ; NumberOfPoints 1 ; } - { GeoElement Line ; NumberOfPoints 4 ; } - { GeoElement Triangle ; NumberOfPoints 6 ; } - { GeoElement Quadrangle ; NumberOfPoints 7 ; } - { GeoElement Tetrahedron ; NumberOfPoints 15 ; } - { GeoElement Hexahedron ; NumberOfPoints 34 ; } - } - } - } - } -} - -Constraint{ - { Name Dirichlet; Type Assign; - Case{ - // Boundary conditions for the V_infinity uniform flow - { Region GammaDown; Value Velocity*BoxSize; } - { Region GammaUp ; Value 0; } - } - } - { Name DeltaPhi; Type Assign; - Case{ - { Region Sur_Cut; Value DeltaPhi[]; } - } - } - { Name MassFlowRate; Type Assign; - Case{ - { Region Sur_Cut; Value MassFlowRate[]; } - } - } -} - -// Domains of definition used in the description of the function space -// These groups contain both volume and surface regions/elements. -Group{ - Dom_Vh = Region[ { Vol_rho, Sur_Dir, Sur_Neu, Sur_Cut } ]; - Dom_Cut = ElementsOf[ Dom_Vh, OnPositiveSideOf Sur_Cut ]; -} -FunctionSpace{ - { Name Vh; Type Form0; - BasisFunction{ - { Name vn; NameOfCoef phin; Function BF_Node; - Support Dom_Vh; Entity NodesOf[All]; } - { Name vc; NameOfCoef dphi; Function BF_GroupOfNodes; - Support Dom_Cut; Entity GroupsOfNodesOf[ Sur_Cut ];} - } - SubSpace { - { Name phiCont ; NameOfBasisFunction { vn } ; } - { Name phiDisc ; NameOfBasisFunction { vc } ; } - } - GlobalQuantity { - { Name Circ ; Type AliasOf ; NameOfCoef dphi ; } - { Name Dmdt ; Type AssociatedWith ; NameOfCoef dphi ; } - } - Constraint{ - {NameOfCoef phin; EntityType NodesOf; - NameOfConstraint Dirichlet;} - If( Flag_Circ ) - {NameOfCoef Circ; EntityType GroupsOfNodesOf; - NameOfConstraint DeltaPhi;} - Else - If( Flag_Object == 0 ) // if Cylinder only - // In case of the Airfoil, the contraint on Dmdt is omitted - // and replaced by an equation "Dmdt=$newDmdt" - // See the "Resolution" section. - {NameOfCoef Dmdt; EntityType GroupsOfNodesOf; - NameOfConstraint MassFlowRate;} - EndIf - EndIf - } - } -} - -Formulation{ - {Name PotentialFlow; Type FemEquation; - Quantity{ - {Name phi; Type Local; NameOfSpace Vh;} - { Name phiCont ; Type Local ; NameOfSpace Vh[phiCont] ; } - { Name phiDisc ; Type Local ; NameOfSpace Vh[phiDisc] ; } - { Name Circ ; Type Global ; NameOfSpace Vh[Circ] ; } - { Name Dmdt ; Type Global ; NameOfSpace Vh[Dmdt] ; } - } - Equation{ - Integral{[ rho[] * Dof{d phi}, {d phi}]; - In Vol_rho; Jacobian Vol; Integration Int;} - If( !Flag_Circ ) - GlobalTerm { [ -Dof{Dmdt} , {Circ} ] ; In Sur_Cut ; } - If( Flag_Object == 1 ) - GlobalTerm { [ -Dof{Dmdt} , {Dmdt} ] ; In Sur_Cut ; } - GlobalTerm { [ $newDmdt , {Dmdt} ] ; In Sur_Cut ; } - EndIf - EndIf - } - } -} - -Resolution{ - {Name PotentialFlow; - System{ - { Name A; NameOfFormulation PotentialFlow; } - } - Operation{ - InitSolution[A]; - - If( Flag_Circ || ( Flag_Object == 0 ) ) - - Generate[A]; Solve[A]; SaveSolution[A]; - PostOperation[Trailing]; - - Else - // A resolution can contain elementary algorithms. - // Available commands are: - // Evaluate[] : affectation of a run-time variable - // Test[]{}{} : logical test - // While[]{} : iteration - // Print[{}, Format ..., File ...] : formatted display - - // A pseudo-Newton iteration is implemented here to determine the value - // of Dmdt (in the Airfoil case) that verifies Kutta's condition. The - // run-time variable $newDmdt is used in Generate[A] whereas $circ, - // $dmdt, $argV and $phiTrailing are evaluated by the - // PostOperation[Trailing]. - - DeleteFile["KJiter.txt"]; - - Evaluate[$newDmdt = MassFlowRate]; - Evaluate[ $syscount = 0 ]; - Generate[A]; Solve[A]; SaveSolution[A]; - - Evaluate[$dmdtp = MassFlowRate]; - Evaluate[$argVp = DeltaPhi]; - PostOperation[Trailing]; - - Print[{$syscount, $circ, $dmdt, $argV}, - Format "iter = %3g Circ = %5.2f Dmdt = %5.2f argV = %5.2e"]; - - While[ Norm[ $argV ] > 1e-3 && $syscount < 50] { - Test[ $syscount && Norm[$argV-$argVp] > 1e-3 ] - {Evaluate[$jac = Min[ ($dmdt-$dmdtp)/($argV-$argVp), 0.2 ] ] ;} - {Evaluate[$jac = 0.2];} - - Evaluate[$newDmdt = $dmdt - $jac * $argV]; - Evaluate[ $syscount = $syscount + 1 ]; - Generate[A]; Solve[A]; SaveSolution[A]; - - Evaluate[$dmdtp = $dmdt]; - Evaluate[$argVp = $argV]; - PostOperation[Trailing]; - - Print[{$syscount, $circ, $dmdt, $jac, $argV}, - Format "iter = %3g Circ = %5.2f Dmdt = %5.2f jac=%5.2f argV = %5.3e"]; - } - EndIf - } - } -} - -PostProcessing{ - { Name PotentialFlow; NameOfFormulation PotentialFlow; - Quantity{ - { Name phi; Value { - Term{ [ {phi} ] ; In Dom_Vh; Jacobian Vol; } - } - } - { Name phiCont ; Value { - Term { [ { phiCont } ] ; In Dom_Vh ; Jacobian Vol ; } - } - } - { Name phiDisc ; Value { - Term { [ { phiDisc } ] ; In Dom_Vh ; Jacobian Vol ; } - } - } - { Name velocity; Value { - Term { [ {d phi} ]; In Dom_Vh; Jacobian Vol; } - } - } - { Name normVelocity; Value { - Term { [ Norm[{d phi}] ]; In Dom_Vh; Jacobian Vol; } - } - } - { Name pressure; Value { - Term { [-0.5*rho[]*SquNorm[ {d phi} ]]; In Dom_Vh; Jacobian Vol; } - } - } - { Name Angle; Value { - Term{ [ argVTrail[{d phi}] ]; In Dom_Vh; Jacobian Vol; } - } - } - { Name Circ; Value { - Term { [ {Circ} ]; In Sur_Cut; } - } - } - { Name Dmdt; Value { - Term { [ {Dmdt} ]; In Sur_Cut; } - } - } - // Kutta-Jukowski approximation for Lift - { Name LiftKJ; Value { - Term { [ -rho[]*{Circ}*Velocity ]; In Sur_Cut; } - } - } - // Lift computed with the real pressure field - { Name Lift; Value { - Integral { [ -0.5*rho[]*SquNorm[{d phi}]*CompY[Normal[]] ]; - In Dom_Vh ; Jacobian Sur ; Integration Int; } - } - } - { Name circulation; Value { - Integral { [ {d phi} * Tangent[] ] ; - In Dom_Vh ; Jacobian Sur ; Integration Int; } - } - } - } - } -} - -PostOperation{ - {Name PotentialFlow; NameOfPostProcessing PotentialFlow; - Operation{ - - Print[Circ, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", - Format Table, SendToServer "Output/Circ" ]; - - Print[Dmdt, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", - Format Table, SendToServer "Output/Dmdt" ]; - - Print[LiftKJ, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", - Format Table, SendToServer "Output/LiftKJ" ]; - - Print[Lift[GammaAirf], OnGlobal, Format Table, - File > "output.txt", Color "Ivory", - SendToServer "Output/Lift"]; - - // Uncomment these lines to have more color maps - //Print[phi, OnElementsOf Vol_rho, File "phi.pos"]; - //Print[phiDisc, OnElementsOf Vol_rho, File "phiDisc.pos"]; - //Print[phiCont, OnElementsOf Vol_rho, File "phiCont.pos"]; - //Print[pressure, OnElementsOf Vol_rho, File "p.pos"]; - - Print[ velocity, OnElementsOf Vol_rho, File "velocity.pos"]; - Echo[ Str["l=PostProcessing.NbViews-1;", - "View[l].VectorType = 1;", - "View[l].LineWidth = 2;", - "View[l].ArrowSizeMax = 100;", - "View[l].CenterGlyphs = 1;"], - File "tmp.geo", LastTimeStepOnly] ; - - // Stagnation points are points where Norm[{d phi}] is zero - // This is better seen in log scale. - Print[normVelocity, OnElementsOf Vol_rho, File "p.pos"]; - Echo[Str["l=PostProcessing.NbViews-1;", - "View[l].Name = 'stagnation points';", - "View[l].ScaleType = 2; // log scale"], - File "tmp.geo"] ; - - If( Flag_Object == 0 ) - Print[phi, OnElementsOf Vol_rho, File "phi.pos"]; - Else - // Show the isovalue "phi=$PhiTrailing" - // which is perpendicular to the airfoil - // iff the Kutta condition is fulfilled - Print[phi, OnElementsOf Vol_rho, File "KJ.pos"]; - Print[{$phiTrailing, 1.001*$phiTrailing}, Format - Str["l=PostProcessing.NbViews-1;", - "View[l].Name = 'isovalue phiTrailing';", - "View[l].IntervalsType = 3;", - "Mesh.SurfaceEdges = 0; // hide mesh", - "View[l].RangeType = 2; // custom range", - "View[l].CustomMin = %g;", - "View[l].CustomMax = %g;"], - File "tmp.geo"] ; - EndIf - } - } -} - -PostOperation{ // for the Airfoil model - { Name Trailing; NameOfPostProcessing PotentialFlow; - Operation{ - Print[Circ, OnRegion Sur_Cut, File > "KJiter.txt", Format Table, - StoreInVariable $circ, - SendToServer "Output/Circ" ]; - Print[Dmdt, OnRegion Sur_Cut, File > "KJiter.txt", Format Table, - StoreInVariable $dmdt, - SendToServer "Output/Dmdt" ]; - // P_edge = {1.0001,0,0} - Print[phi, OnPoint {1.0001,0,0}, File > "KJiter.txt", Color "Ivory", - StoreInVariable $phiTrailing, - Format Table, SendToServer "Output/PhiTrailing"]; - - Print[Angle, OnPoint{1.0001,0,0}, File > "KJiter.txt", Color "Ivory", - StoreInVariable $argV, - Format Table, SendToServer "Output/argVTrailing"]; - } - } -} - -DefineConstant[ - R_ = {"PotentialFlow", Name "GetDP/1ResolutionChoices", Visible 0}, - C_ = {"-solve -pos", Name "GetDP/9ComputeCommand", Visible 0}, - P_ = {"PotentialFlow", Name "GetDP/2PostOperationChoices", Visible 0} -]; +/* ------------------------------------------------------------------- + Tutorial 6 : Potential flow and Magnus effect + + Features: + - Potential flow, irrotational flow + - Multivalued scalar field + - Lift and Magnus effect, stagnation points + - Run-time variables + - Elementary algorithms in the Resolution section + - Non-linear iteration to achieve Kutta's condition + + To compute the solution in a terminal: + getdp magnus.pro -solve PotentialFlow -pos PotentialFlow + gmsh magnus.geo velocity.pos + + To compute the solution interactively from the Gmsh GUI: + File > Open > magnus.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* This model solves a 2D potential flow around a cylinder or a naca airfoil + placed in a uniform "V_infinity" flow. Potential flows are defined by + + V = grad phi => curl V = 0 + + where the multivalued scalar potential "phi" presents a discontinuity of + magnitude "deltaPhi" across a cut "Sur_Cut". In consequence, the velocity + field "V" is curl-free over the wole domain of analysis "Vol_rho" but its + circulation over any closed curve circling around the object, a quantity + often noted "Gamma" in the literature, gives "deltaPhi" as a result. The + circulation of "V" over closed curves not circling around the object is zero. + + In the GetDP model, the discontinuity "deltaPhi" [m^2/s] is defined as a + global quantity in the Functional space of "phi". The associated (dual) + global quantity is the mass flow density, noted "Dmdt", which has [kg/s] as a + unit. + + Governing equations are + + div ( rho[] grad phi ) = 0 in Vol_rho + rho[] grad phi . n = rho[] Vn = 0 on Sur_Neu + + whereas the uniform velocity field "V_infinity" is imposed by means of + Dirichlet boundary conditions on the upstream and downstream surfaces + "GammaUp" and "GammaDown". + + Momentum equation is decoupled in case of stationary potential flows. The + velocity filed can be solved first, and the pressure is obtained afterwards + by invoking Bernoulli's theorem: + + p = -0.5 * rho[] * SquNorm [ {d phi} ] + + The "Lift" force in "Y" direction is then evaluated either by integrating "p + * CompY[Normal[]]" over the contour of the object, or by the Kutta-Jukowski + theorem + + Lift = - L_z rho[] V_infinity Gamma + + which is a first order approximation of the former. + + "Cylinder" case: + + Either the circulation "deltaPhi" or the mass flow rate "Dmdt" can be + imposed, according to the "Flag_Circ" flag. The Lift is evaluated by both + the integration of pressure and the Kutta-Jukowski approximation. + + "Airfoil" case: + + - If "Flag_Circ == 1", the model works similar to the "Cylinder" case. + + - If "Flag_Circ == 0", the mass flow rate is not directly imposed in this + case. It is determined so that the Kutta condition is verified. This + condition states that the actual value of "Dmdt" is the one for which the + stagnation point (singularity of the velocity field) is located at the + trailing edge of the airfoil,. This is true when the function + + argVTrail[] = ( Atan2[CompY[$1], CompX[$1] ] - Incidence ) / deg ; + + returns zero when evaluated for the velocity at a point "P_edge" close to + the trailing edge of the airfoil. A non linear iteration is thus done by + means of a pseudo-newton scheme, updating the value of the imposed "Dmdt" + until the norm of the residual + + f(V) = argVTrail[ {d phi } ] OnPoint {1.0001,0,0} + + comes below a fixed tolerance. */ + +Include "magnus_common.pro"; + +Group{ + // Physical regions + Fluid = Region[ 2 ]; + GammaUp = Region[ 10 ]; + GammaDown = Region[ 11 ]; + GammaAirf = Region[ 12 ]; + GammaCut = Region[ 13 ]; + + // Abstract regions + Vol_rho = Region[ { Fluid } ]; + Sur_Dir = Region[ { GammaUp, GammaDown } ]; + Sur_Neu = Region[ { GammaAirf } ]; + Sur_Cut = Region[ { GammaCut } ]; +} + +Function{ + rho[] = 1.225; // kg/m^3 + MassFlowRate[] = MassFlowRate; // kg/s + DeltaPhi[] = DeltaPhi; // m^2/s + argVTrail[] = ( Atan2[CompY[$1], CompX[$1] ] - Incidence ) / deg ; +} + +Jacobian { + { Name Vol ; + Case { + { Region All ; Jacobian Vol ; } + } + } + { Name Sur ; + Case { + { Region All ; Jacobian Sur ; } + } + } +} + +Integration { + { Name Int ; + Case { + { Type Gauss ; + Case { + { GeoElement Point ; NumberOfPoints 1 ; } + { GeoElement Line ; NumberOfPoints 4 ; } + { GeoElement Triangle ; NumberOfPoints 6 ; } + { GeoElement Quadrangle ; NumberOfPoints 7 ; } + { GeoElement Tetrahedron ; NumberOfPoints 15 ; } + { GeoElement Hexahedron ; NumberOfPoints 34 ; } + } + } + } + } +} + +Constraint{ + { Name Dirichlet; Type Assign; + Case{ + // Boundary conditions for the V_infinity uniform flow + { Region GammaDown; Value Velocity*BoxSize; } + { Region GammaUp ; Value 0; } + } + } + { Name DeltaPhi; Type Assign; + Case{ + { Region Sur_Cut; Value DeltaPhi[]; } + } + } + { Name MassFlowRate; Type Assign; + Case{ + { Region Sur_Cut; Value MassFlowRate[]; } + } + } +} + +// Domains of definition used in the description of the function space +// These groups contain both volume and surface regions/elements. +Group{ + Dom_Vh = Region[ { Vol_rho, Sur_Dir, Sur_Neu, Sur_Cut } ]; + Dom_Cut = ElementsOf[ Dom_Vh, OnPositiveSideOf Sur_Cut ]; +} +FunctionSpace{ + { Name Vh; Type Form0; + BasisFunction{ + { Name vn; NameOfCoef phin; Function BF_Node; + Support Dom_Vh; Entity NodesOf[All]; } + { Name vc; NameOfCoef dphi; Function BF_GroupOfNodes; + Support Dom_Cut; Entity GroupsOfNodesOf[ Sur_Cut ];} + } + SubSpace { + { Name phiCont ; NameOfBasisFunction { vn } ; } + { Name phiDisc ; NameOfBasisFunction { vc } ; } + } + GlobalQuantity { + { Name Circ ; Type AliasOf ; NameOfCoef dphi ; } + { Name Dmdt ; Type AssociatedWith ; NameOfCoef dphi ; } + } + Constraint{ + {NameOfCoef phin; EntityType NodesOf; + NameOfConstraint Dirichlet;} + If( Flag_Circ ) + {NameOfCoef Circ; EntityType GroupsOfNodesOf; + NameOfConstraint DeltaPhi;} + Else + If( Flag_Object == 0 ) // if Cylinder only + // In case of the Airfoil, the contraint on Dmdt is omitted + // and replaced by an equation "Dmdt=$newDmdt" + // See the "Resolution" section. + {NameOfCoef Dmdt; EntityType GroupsOfNodesOf; + NameOfConstraint MassFlowRate;} + EndIf + EndIf + } + } +} + +Formulation{ + {Name PotentialFlow; Type FemEquation; + Quantity{ + {Name phi; Type Local; NameOfSpace Vh;} + { Name phiCont ; Type Local ; NameOfSpace Vh[phiCont] ; } + { Name phiDisc ; Type Local ; NameOfSpace Vh[phiDisc] ; } + { Name Circ ; Type Global ; NameOfSpace Vh[Circ] ; } + { Name Dmdt ; Type Global ; NameOfSpace Vh[Dmdt] ; } + } + Equation{ + Integral{[ rho[] * Dof{d phi}, {d phi}]; + In Vol_rho; Jacobian Vol; Integration Int;} + If( !Flag_Circ ) + GlobalTerm { [ -Dof{Dmdt} , {Circ} ] ; In Sur_Cut ; } + If( Flag_Object == 1 ) + GlobalTerm { [ -Dof{Dmdt} , {Dmdt} ] ; In Sur_Cut ; } + GlobalTerm { [ $newDmdt , {Dmdt} ] ; In Sur_Cut ; } + EndIf + EndIf + } + } +} + +Resolution{ + {Name PotentialFlow; + System{ + { Name A; NameOfFormulation PotentialFlow; } + } + Operation{ + InitSolution[A]; + + If( Flag_Circ || ( Flag_Object == 0 ) ) + + Generate[A]; Solve[A]; SaveSolution[A]; + PostOperation[Trailing]; + + Else + // A resolution can contain elementary algorithms. + // Available commands are: + // Evaluate[] : affectation of a run-time variable + // Test[]{}{} : logical test + // While[]{} : iteration + // Print[{}, Format ..., File ...] : formatted display + + // A pseudo-Newton iteration is implemented here to determine the value + // of Dmdt (in the Airfoil case) that verifies Kutta's condition. The + // run-time variable $newDmdt is used in Generate[A] whereas $circ, + // $dmdt, $argV and $phiTrailing are evaluated by the + // PostOperation[Trailing]. + + DeleteFile["KJiter.txt"]; + + Evaluate[$newDmdt = MassFlowRate]; + Evaluate[ $syscount = 0 ]; + Generate[A]; Solve[A]; SaveSolution[A]; + + Evaluate[$dmdtp = MassFlowRate]; + Evaluate[$argVp = DeltaPhi]; + PostOperation[Trailing]; + + Print[{$syscount, $circ, $dmdt, $argV}, + Format "iter = %3g Circ = %5.2f Dmdt = %5.2f argV = %5.2e"]; + + While[ Norm[ $argV ] > 1e-3 && $syscount < 50] { + Test[ $syscount && Norm[$argV-$argVp] > 1e-3 ] + {Evaluate[$jac = Min[ ($dmdt-$dmdtp)/($argV-$argVp), 0.2 ] ] ;} + {Evaluate[$jac = 0.2];} + + Evaluate[$newDmdt = $dmdt - $jac * $argV]; + Evaluate[ $syscount = $syscount + 1 ]; + Generate[A]; Solve[A]; SaveSolution[A]; + + Evaluate[$dmdtp = $dmdt]; + Evaluate[$argVp = $argV]; + PostOperation[Trailing]; + + Print[{$syscount, $circ, $dmdt, $jac, $argV}, + Format "iter = %3g Circ = %5.2f Dmdt = %5.2f jac=%5.2f argV = %5.3e"]; + } + EndIf + } + } +} + +PostProcessing{ + { Name PotentialFlow; NameOfFormulation PotentialFlow; + Quantity{ + { Name phi; Value { + Term{ [ {phi} ] ; In Dom_Vh; Jacobian Vol; } + } + } + { Name phiCont ; Value { + Term { [ { phiCont } ] ; In Dom_Vh ; Jacobian Vol ; } + } + } + { Name phiDisc ; Value { + Term { [ { phiDisc } ] ; In Dom_Vh ; Jacobian Vol ; } + } + } + { Name velocity; Value { + Term { [ {d phi} ]; In Dom_Vh; Jacobian Vol; } + } + } + { Name normVelocity; Value { + Term { [ Norm[{d phi}] ]; In Dom_Vh; Jacobian Vol; } + } + } + { Name pressure; Value { + Term { [-0.5*rho[]*SquNorm[ {d phi} ]]; In Dom_Vh; Jacobian Vol; } + } + } + { Name Angle; Value { + Term{ [ argVTrail[{d phi}] ]; In Dom_Vh; Jacobian Vol; } + } + } + { Name Circ; Value { + Term { [ {Circ} ]; In Sur_Cut; } + } + } + { Name Dmdt; Value { + Term { [ {Dmdt} ]; In Sur_Cut; } + } + } + // Kutta-Jukowski approximation for Lift + { Name LiftKJ; Value { + Term { [ -rho[]*{Circ}*Velocity ]; In Sur_Cut; } + } + } + // Lift computed with the real pressure field + { Name Lift; Value { + Integral { [ -0.5*rho[]*SquNorm[{d phi}]*CompY[Normal[]] ]; + In Dom_Vh ; Jacobian Sur ; Integration Int; } + } + } + { Name circulation; Value { + Integral { [ {d phi} * Tangent[] ] ; + In Dom_Vh ; Jacobian Sur ; Integration Int; } + } + } + } + } +} + +PostOperation{ + {Name PotentialFlow; NameOfPostProcessing PotentialFlow; + Operation{ + + Print[Circ, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", + Format Table, SendToServer "Output/Circ" ]; + + Print[Dmdt, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", + Format Table, SendToServer "Output/Dmdt" ]; + + Print[LiftKJ, OnRegion Sur_Cut, File > "output.txt", Color "Ivory", + Format Table, SendToServer "Output/LiftKJ" ]; + + Print[Lift[GammaAirf], OnGlobal, Format Table, + File > "output.txt", Color "Ivory", + SendToServer "Output/Lift"]; + + // Uncomment these lines to have more color maps + //Print[phi, OnElementsOf Vol_rho, File "phi.pos"]; + //Print[phiDisc, OnElementsOf Vol_rho, File "phiDisc.pos"]; + //Print[phiCont, OnElementsOf Vol_rho, File "phiCont.pos"]; + //Print[pressure, OnElementsOf Vol_rho, File "p.pos"]; + + Print[ velocity, OnElementsOf Vol_rho, File "velocity.pos"]; + Echo[ Str["l=PostProcessing.NbViews-1;", + "View[l].VectorType = 1;", + "View[l].LineWidth = 2;", + "View[l].ArrowSizeMax = 100;", + "View[l].CenterGlyphs = 1;"], + File "tmp.geo", LastTimeStepOnly] ; + + // Stagnation points are points where Norm[{d phi}] is zero + // This is better seen in log scale. + Print[normVelocity, OnElementsOf Vol_rho, File "p.pos"]; + Echo[Str["l=PostProcessing.NbViews-1;", + "View[l].Name = 'stagnation points';", + "View[l].ScaleType = 2; // log scale"], + File "tmp.geo"] ; + + If( Flag_Object == 0 ) + Print[phi, OnElementsOf Vol_rho, File "phi.pos"]; + Else + // Show the isovalue "phi=$PhiTrailing" + // which is perpendicular to the airfoil + // iff the Kutta condition is fulfilled + Print[phi, OnElementsOf Vol_rho, File "KJ.pos"]; + Print[{$phiTrailing, 1.001*$phiTrailing}, Format + Str["l=PostProcessing.NbViews-1;", + "View[l].Name = 'isovalue phiTrailing';", + "View[l].IntervalsType = 3;", + "Mesh.SurfaceEdges = 0; // hide mesh", + "View[l].RangeType = 2; // custom range", + "View[l].CustomMin = %g;", + "View[l].CustomMax = %g;"], + File "tmp.geo"] ; + EndIf + } + } +} + +PostOperation{ // for the Airfoil model + { Name Trailing; NameOfPostProcessing PotentialFlow; + Operation{ + Print[Circ, OnRegion Sur_Cut, File > "KJiter.txt", Format Table, + StoreInVariable $circ, + SendToServer "Output/Circ" ]; + Print[Dmdt, OnRegion Sur_Cut, File > "KJiter.txt", Format Table, + StoreInVariable $dmdt, + SendToServer "Output/Dmdt" ]; + // P_edge = {1.0001,0,0} + Print[phi, OnPoint {1.0001,0,0}, File > "KJiter.txt", Color "Ivory", + StoreInVariable $phiTrailing, + Format Table, SendToServer "Output/PhiTrailing"]; + + Print[Angle, OnPoint{1.0001,0,0}, File > "KJiter.txt", Color "Ivory", + StoreInVariable $argV, + Format Table, SendToServer "Output/argVTrailing"]; + } + } +} + +DefineConstant[ + R_ = {"PotentialFlow", Name "GetDP/1ResolutionChoices", Visible 0}, + C_ = {"-solve -pos", Name "GetDP/9ComputeCommand", Visible 0}, + P_ = {"PotentialFlow", Name "GetDP/2PostOperationChoices", Visible 0} +]; diff --git a/PotentialFlow/magnus_common.pro b/PotentialFlow/magnus_common.pro index f1c65c4..b9c659b 100644 --- a/PotentialFlow/magnus_common.pro +++ b/PotentialFlow/magnus_common.pro @@ -1,27 +1,27 @@ -cm = 1e-2; -deg = Pi/180; -kmh = 10./36.; - -Flag_Circ = - DefineNumber[0, Name "Model/Impose circulation", Choices {0, 1} ]; -Flag_Object = - DefineNumber[1, Name "Model/Object", - Choices {0="Cylinder", 1="Airfoil"} ]; - -BoxSize = - DefineNumber[7, Name "Model/Air box size [m]", Help "In flow direction."]; -Velocity = kmh* - DefineNumber[100, Name "Model/V", Label "Model/Flow velocity [km/h]"]; -Incidence = -deg* - DefineNumber[10, Name "Model/Angle of attack [deg]", Visible Flag_Object]; - -// Negative circulation for a positive lift. -DeltaPhi = (-1)* - DefineNumber[10, Name "Model/Circ", Visible Flag_Circ, - Min 0, Max 20, Step 2, - Label "Circulation around foil [m^2/s]"]; - -MassFlowRate = - DefineNumber[-100, Name "Model/Dmdt", Visible !Flag_Circ, - Label "Mass flow rate [kg/s]"]; - +cm = 1e-2; +deg = Pi/180; +kmh = 10./36.; + +Flag_Circ = + DefineNumber[0, Name "Model/Impose circulation", Choices {0, 1} ]; +Flag_Object = + DefineNumber[1, Name "Model/Object", + Choices {0="Cylinder", 1="Airfoil"} ]; + +BoxSize = + DefineNumber[7, Name "Model/Air box size [m]", Help "In flow direction."]; +Velocity = kmh* + DefineNumber[100, Name "Model/V", Label "Model/Flow velocity [km/h]"]; +Incidence = -deg* + DefineNumber[10, Name "Model/Angle of attack [deg]", Visible Flag_Object]; + +// Negative circulation for a positive lift. +DeltaPhi = (-1)* + DefineNumber[10, Name "Model/Circ", Visible Flag_Circ, + Min 0, Max 20, Step 2, + Label "Circulation around foil [m^2/s]"]; + +MassFlowRate = + DefineNumber[-100, Name "Model/Dmdt", Visible !Flag_Circ, + Label "Mass flow rate [kg/s]"]; + diff --git a/PotentialFlow/nacaAirfoil.geo b/PotentialFlow/nacaAirfoil.geo index 764a17d..9ef6199 100644 --- a/PotentialFlow/nacaAirfoil.geo +++ b/PotentialFlow/nacaAirfoil.geo @@ -1,222 +1,222 @@ - - -Point(1) = {1.000000,0.000000,0,lca}; -Point(2) = {0.999753,-0.000035,0,lca}; -Point(3) = {0.999013,-0.000141,0,lca}; -Point(4) = {0.997781,-0.000317,0,lca}; -Point(5) = {0.996057,-0.000562,0,lca}; -Point(6) = {0.993844,-0.000876,0,lca}; -Point(7) = {0.991144,-0.001258,0,lca}; -Point(8) = {0.987958,-0.001707,0,lca}; -Point(9) = {0.984292,-0.002222,0,lca}; -Point(10) = {0.980147,-0.002801,0,lca}; -Point(11) = {0.975528,-0.003443,0,lca}; -Point(12) = {0.970440,-0.004147,0,lca}; -Point(13) = {0.964888,-0.004909,0,lca}; -Point(14) = {0.958877,-0.005729,0,lca}; -Point(15) = {0.952414,-0.006603,0,lca}; -Point(16) = {0.945503,-0.007531,0,lca}; -Point(17) = {0.938153,-0.008510,0,lca}; -Point(18) = {0.930371,-0.009537,0,lca}; -Point(19) = {0.922164,-0.010610,0,lca}; -Point(20) = {0.913540,-0.011726,0,lca}; -Point(21) = {0.904508,-0.012883,0,lca}; -Point(22) = {0.895078,-0.014079,0,lca}; -Point(23) = {0.885257,-0.015310,0,lca}; -Point(24) = {0.875056,-0.016574,0,lca}; -Point(25) = {0.864484,-0.017868,0,lca}; -Point(26) = {0.853553,-0.019189,0,lca}; -Point(27) = {0.842274,-0.020535,0,lca}; -Point(28) = {0.830656,-0.021904,0,lca}; -Point(29) = {0.818712,-0.023291,0,lca}; -Point(30) = {0.806454,-0.024694,0,lca}; -Point(31) = {0.793893,-0.026111,0,lca}; -Point(32) = {0.781042,-0.027539,0,lca}; -Point(33) = {0.767913,-0.028974,0,lca}; -Point(34) = {0.754521,-0.030414,0,lca}; -Point(35) = {0.740877,-0.031856,0,lca}; -Point(36) = {0.726995,-0.033296,0,lca}; -Point(37) = {0.712890,-0.034733,0,lca}; -Point(38) = {0.698574,-0.036163,0,lca}; -Point(39) = {0.684062,-0.037582,0,lca}; -Point(40) = {0.669369,-0.038988,0,lca}; -Point(41) = {0.654508,-0.040378,0,lca}; -Point(42) = {0.639496,-0.041747,0,lca}; -Point(43) = {0.624345,-0.043094,0,lca}; -Point(44) = {0.609072,-0.044414,0,lca}; -Point(45) = {0.593691,-0.045705,0,lca}; -Point(46) = {0.578217,-0.046962,0,lca}; -Point(47) = {0.562667,-0.048182,0,lca}; -Point(48) = {0.547054,-0.049362,0,lca}; -Point(49) = {0.531395,-0.050499,0,lca}; -Point(50) = {0.515705,-0.051587,0,lca}; -Point(51) = {0.500000,-0.052625,0,lca}; -Point(52) = {0.484295,-0.053608,0,lca}; -Point(53) = {0.468605,-0.054534,0,lca}; -Point(54) = {0.452946,-0.055397,0,lca}; -Point(55) = {0.437333,-0.056195,0,lca}; -Point(56) = {0.421783,-0.056924,0,lca}; -Point(57) = {0.406309,-0.057581,0,lca}; -Point(58) = {0.390928,-0.058163,0,lca}; -Point(59) = {0.375655,-0.058666,0,lca}; -Point(60) = {0.360504,-0.059087,0,lca}; -Point(61) = {0.345492,-0.059424,0,lca}; -Point(62) = {0.330631,-0.059674,0,lca}; -Point(63) = {0.315938,-0.059834,0,lca}; -Point(64) = {0.301426,-0.059902,0,lca}; -Point(65) = {0.287110,-0.059876,0,lca}; -Point(66) = {0.273005,-0.059754,0,lca}; -Point(67) = {0.259123,-0.059535,0,lca}; -Point(68) = {0.245479,-0.059217,0,lca}; -Point(69) = {0.232087,-0.058799,0,lca}; -Point(70) = {0.218958,-0.058280,0,lca}; -Point(71) = {0.206107,-0.057661,0,lca}; -Point(72) = {0.193546,-0.056940,0,lca}; -Point(73) = {0.181288,-0.056119,0,lca}; -Point(74) = {0.169344,-0.055197,0,lca}; -Point(75) = {0.157726,-0.054176,0,lca}; -Point(76) = {0.146447,-0.053056,0,lca}; -Point(77) = {0.135516,-0.051839,0,lca}; -Point(78) = {0.124944,-0.050527,0,lca}; -Point(79) = {0.114743,-0.049121,0,lca}; -Point(80) = {0.104922,-0.047624,0,lca}; -Point(81) = {0.095492,-0.046037,0,lca}; -Point(82) = {0.086460,-0.044364,0,lca}; -Point(83) = {0.077836,-0.042608,0,lca}; -Point(84) = {0.069629,-0.040770,0,lca}; -Point(85) = {0.061847,-0.038854,0,lca}; -Point(86) = {0.054497,-0.036863,0,lca}; -Point(87) = {0.047586,-0.034800,0,lca}; -Point(88) = {0.041123,-0.032668,0,lca}; -Point(89) = {0.035112,-0.030471,0,lca}; -Point(90) = {0.029560,-0.028212,0,lca}; -Point(91) = {0.024472,-0.025893,0,lca}; -Point(92) = {0.019853,-0.023517,0,lca}; -Point(93) = {0.015708,-0.021088,0,lca}; -Point(94) = {0.012042,-0.018607,0,lca}; -Point(95) = {0.008856,-0.016078,0,lca}; -Point(96) = {0.006156,-0.013503,0,lca}; -Point(97) = {0.003943,-0.010884,0,lca}; -Point(98) = {0.002219,-0.008223,0,lca}; -Point(99) = {0.000987,-0.005521,0,lca}; -Point(100) = {0.000247,-0.002779,0,lca}; -Point(101) = {0.000000,0.000000,0,lca}; -Point(102) = {0.000247,0.002779,0,lca}; -Point(103) = {0.000987,0.005521,0,lca}; -Point(104) = {0.002219,0.008223,0,lca}; -Point(105) = {0.003943,0.010884,0,lca}; -Point(106) = {0.006156,0.013503,0,lca}; -Point(107) = {0.008856,0.016078,0,lca}; -Point(108) = {0.012042,0.018607,0,lca}; -Point(109) = {0.015708,0.021088,0,lca}; -Point(110) = {0.019853,0.023517,0,lca}; -Point(111) = {0.024472,0.025893,0,lca}; -Point(112) = {0.029560,0.028212,0,lca}; -Point(113) = {0.035112,0.030471,0,lca}; -Point(114) = {0.041123,0.032668,0,lca}; -Point(115) = {0.047586,0.034800,0,lca}; -Point(116) = {0.054497,0.036863,0,lca}; -Point(117) = {0.061847,0.038854,0,lca}; -Point(118) = {0.069629,0.040770,0,lca}; -Point(119) = {0.077836,0.042608,0,lca}; -Point(120) = {0.086460,0.044364,0,lca}; -Point(121) = {0.095492,0.046037,0,lca}; -Point(122) = {0.104922,0.047624,0,lca}; -Point(123) = {0.114743,0.049121,0,lca}; -Point(124) = {0.124944,0.050527,0,lca}; -Point(125) = {0.135516,0.051839,0,lca}; -Point(126) = {0.146447,0.053056,0,lca}; -Point(127) = {0.157726,0.054176,0,lca}; -Point(128) = {0.169344,0.055197,0,lca}; -Point(129) = {0.181288,0.056119,0,lca}; -Point(130) = {0.193546,0.056940,0,lca}; -Point(131) = {0.206107,0.057661,0,lca}; -Point(132) = {0.218958,0.058280,0,lca}; -Point(133) = {0.232087,0.058799,0,lca}; -Point(134) = {0.245479,0.059217,0,lca}; -Point(135) = {0.259123,0.059535,0,lca}; -Point(136) = {0.273005,0.059754,0,lca}; -Point(137) = {0.287110,0.059876,0,lca}; -Point(138) = {0.301426,0.059902,0,lca}; -Point(139) = {0.315938,0.059834,0,lca}; -Point(140) = {0.330631,0.059674,0,lca}; -Point(141) = {0.345492,0.059424,0,lca}; -Point(142) = {0.360504,0.059087,0,lca}; -Point(143) = {0.375655,0.058666,0,lca}; -Point(144) = {0.390928,0.058163,0,lca}; -Point(145) = {0.406309,0.057581,0,lca}; -Point(146) = {0.421783,0.056924,0,lca}; -Point(147) = {0.437333,0.056195,0,lca}; -Point(148) = {0.452946,0.055397,0,lca}; -Point(149) = {0.468605,0.054534,0,lca}; -Point(150) = {0.484295,0.053608,0,lca}; -Point(151) = {0.500000,0.052625,0,lca}; -Point(152) = {0.515705,0.051587,0,lca}; -Point(153) = {0.531395,0.050499,0,lca}; -Point(154) = {0.547054,0.049362,0,lca}; -Point(155) = {0.562667,0.048182,0,lca}; -Point(156) = {0.578217,0.046962,0,lca}; -Point(157) = {0.593691,0.045705,0,lca}; -Point(158) = {0.609072,0.044414,0,lca}; -Point(159) = {0.624345,0.043094,0,lca}; -Point(160) = {0.639496,0.041747,0,lca}; -Point(161) = {0.654508,0.040378,0,lca}; -Point(162) = {0.669369,0.038988,0,lca}; -Point(163) = {0.684062,0.037582,0,lca}; -Point(164) = {0.698574,0.036163,0,lca}; -Point(165) = {0.712890,0.034733,0,lca}; -Point(166) = {0.726995,0.033296,0,lca}; -Point(167) = {0.740877,0.031856,0,lca}; -Point(168) = {0.754521,0.030414,0,lca}; -Point(169) = {0.767913,0.028974,0,lca}; -Point(170) = {0.781042,0.027539,0,lca}; -Point(171) = {0.793893,0.026111,0,lca}; -Point(172) = {0.806454,0.024694,0,lca}; -Point(173) = {0.818712,0.023291,0,lca}; -Point(174) = {0.830656,0.021904,0,lca}; -Point(175) = {0.842274,0.020535,0,lca}; -Point(176) = {0.853553,0.019189,0,lca}; -Point(177) = {0.864484,0.017868,0,lca}; -Point(178) = {0.875056,0.016574,0,lca}; -Point(179) = {0.885257,0.015310,0,lca}; -Point(180) = {0.895078,0.014079,0,lca}; -Point(181) = {0.904508,0.012883,0,lca}; -Point(182) = {0.913540,0.011726,0,lca}; -Point(183) = {0.922164,0.010610,0,lca}; -Point(184) = {0.930371,0.009537,0,lca}; -Point(185) = {0.938153,0.008510,0,lca}; -Point(186) = {0.945503,0.007531,0,lca}; -Point(187) = {0.952414,0.006603,0,lca}; -Point(188) = {0.958877,0.005729,0,lca}; -Point(189) = {0.964888,0.004909,0,lca}; -Point(190) = {0.970440,0.004147,0,lca}; -Point(191) = {0.975528,0.003443,0,lca}; -Point(192) = {0.980147,0.002801,0,lca}; -Point(193) = {0.984292,0.002222,0,lca}; -Point(194) = {0.987958,0.001707,0,lca}; -Point(195) = {0.991144,0.001258,0,lca}; -Point(196) = {0.993844,0.000876,0,lca}; -Point(197) = {0.996057,0.000562,0,lca}; -Point(198) = {0.997781,0.000317,0,lca}; -Point(199) = {0.999013,0.000141,0,lca}; -Point(200) = {0.999753,0.000035,0,lca}; - -//Points numerotation: -numberLeadingEgde = 101 ; -numberLowerSurface = 81 ; -numberUpperSurface = 121 ; - -//Distances: -distanceTrailingLowerPoint = 0.908262 ; -distanceLowerUpperPoint = 0.222905 ; -distanceUpperTrailingPoint = 0.908262 ; - -Line(1) = { 1 ... 81 }; -Line(2) = { 81 ... 101 }; -Line(3) = { 101 ... 121 }; -Line(4) = { 121 ... 200, 1 }; - -Rotate { {0,0,1}, {1,0,0}, Incidence } { Line { 1 ... 4 } ; } - -/* Line Loop(1) = {1,2,3,4}; */ -/* Plane Surface(1) = {1}; */ + + +Point(1) = {1.000000,0.000000,0,lca}; +Point(2) = {0.999753,-0.000035,0,lca}; +Point(3) = {0.999013,-0.000141,0,lca}; +Point(4) = {0.997781,-0.000317,0,lca}; +Point(5) = {0.996057,-0.000562,0,lca}; +Point(6) = {0.993844,-0.000876,0,lca}; +Point(7) = {0.991144,-0.001258,0,lca}; +Point(8) = {0.987958,-0.001707,0,lca}; +Point(9) = {0.984292,-0.002222,0,lca}; +Point(10) = {0.980147,-0.002801,0,lca}; +Point(11) = {0.975528,-0.003443,0,lca}; +Point(12) = {0.970440,-0.004147,0,lca}; +Point(13) = {0.964888,-0.004909,0,lca}; +Point(14) = {0.958877,-0.005729,0,lca}; +Point(15) = {0.952414,-0.006603,0,lca}; +Point(16) = {0.945503,-0.007531,0,lca}; +Point(17) = {0.938153,-0.008510,0,lca}; +Point(18) = {0.930371,-0.009537,0,lca}; +Point(19) = {0.922164,-0.010610,0,lca}; +Point(20) = {0.913540,-0.011726,0,lca}; +Point(21) = {0.904508,-0.012883,0,lca}; +Point(22) = {0.895078,-0.014079,0,lca}; +Point(23) = {0.885257,-0.015310,0,lca}; +Point(24) = {0.875056,-0.016574,0,lca}; +Point(25) = {0.864484,-0.017868,0,lca}; +Point(26) = {0.853553,-0.019189,0,lca}; +Point(27) = {0.842274,-0.020535,0,lca}; +Point(28) = {0.830656,-0.021904,0,lca}; +Point(29) = {0.818712,-0.023291,0,lca}; +Point(30) = {0.806454,-0.024694,0,lca}; +Point(31) = {0.793893,-0.026111,0,lca}; +Point(32) = {0.781042,-0.027539,0,lca}; +Point(33) = {0.767913,-0.028974,0,lca}; +Point(34) = {0.754521,-0.030414,0,lca}; +Point(35) = {0.740877,-0.031856,0,lca}; +Point(36) = {0.726995,-0.033296,0,lca}; +Point(37) = {0.712890,-0.034733,0,lca}; +Point(38) = {0.698574,-0.036163,0,lca}; +Point(39) = {0.684062,-0.037582,0,lca}; +Point(40) = {0.669369,-0.038988,0,lca}; +Point(41) = {0.654508,-0.040378,0,lca}; +Point(42) = {0.639496,-0.041747,0,lca}; +Point(43) = {0.624345,-0.043094,0,lca}; +Point(44) = {0.609072,-0.044414,0,lca}; +Point(45) = {0.593691,-0.045705,0,lca}; +Point(46) = {0.578217,-0.046962,0,lca}; +Point(47) = {0.562667,-0.048182,0,lca}; +Point(48) = {0.547054,-0.049362,0,lca}; +Point(49) = {0.531395,-0.050499,0,lca}; +Point(50) = {0.515705,-0.051587,0,lca}; +Point(51) = {0.500000,-0.052625,0,lca}; +Point(52) = {0.484295,-0.053608,0,lca}; +Point(53) = {0.468605,-0.054534,0,lca}; +Point(54) = {0.452946,-0.055397,0,lca}; +Point(55) = {0.437333,-0.056195,0,lca}; +Point(56) = {0.421783,-0.056924,0,lca}; +Point(57) = {0.406309,-0.057581,0,lca}; +Point(58) = {0.390928,-0.058163,0,lca}; +Point(59) = {0.375655,-0.058666,0,lca}; +Point(60) = {0.360504,-0.059087,0,lca}; +Point(61) = {0.345492,-0.059424,0,lca}; +Point(62) = {0.330631,-0.059674,0,lca}; +Point(63) = {0.315938,-0.059834,0,lca}; +Point(64) = {0.301426,-0.059902,0,lca}; +Point(65) = {0.287110,-0.059876,0,lca}; +Point(66) = {0.273005,-0.059754,0,lca}; +Point(67) = {0.259123,-0.059535,0,lca}; +Point(68) = {0.245479,-0.059217,0,lca}; +Point(69) = {0.232087,-0.058799,0,lca}; +Point(70) = {0.218958,-0.058280,0,lca}; +Point(71) = {0.206107,-0.057661,0,lca}; +Point(72) = {0.193546,-0.056940,0,lca}; +Point(73) = {0.181288,-0.056119,0,lca}; +Point(74) = {0.169344,-0.055197,0,lca}; +Point(75) = {0.157726,-0.054176,0,lca}; +Point(76) = {0.146447,-0.053056,0,lca}; +Point(77) = {0.135516,-0.051839,0,lca}; +Point(78) = {0.124944,-0.050527,0,lca}; +Point(79) = {0.114743,-0.049121,0,lca}; +Point(80) = {0.104922,-0.047624,0,lca}; +Point(81) = {0.095492,-0.046037,0,lca}; +Point(82) = {0.086460,-0.044364,0,lca}; +Point(83) = {0.077836,-0.042608,0,lca}; +Point(84) = {0.069629,-0.040770,0,lca}; +Point(85) = {0.061847,-0.038854,0,lca}; +Point(86) = {0.054497,-0.036863,0,lca}; +Point(87) = {0.047586,-0.034800,0,lca}; +Point(88) = {0.041123,-0.032668,0,lca}; +Point(89) = {0.035112,-0.030471,0,lca}; +Point(90) = {0.029560,-0.028212,0,lca}; +Point(91) = {0.024472,-0.025893,0,lca}; +Point(92) = {0.019853,-0.023517,0,lca}; +Point(93) = {0.015708,-0.021088,0,lca}; +Point(94) = {0.012042,-0.018607,0,lca}; +Point(95) = {0.008856,-0.016078,0,lca}; +Point(96) = {0.006156,-0.013503,0,lca}; +Point(97) = {0.003943,-0.010884,0,lca}; +Point(98) = {0.002219,-0.008223,0,lca}; +Point(99) = {0.000987,-0.005521,0,lca}; +Point(100) = {0.000247,-0.002779,0,lca}; +Point(101) = {0.000000,0.000000,0,lca}; +Point(102) = {0.000247,0.002779,0,lca}; +Point(103) = {0.000987,0.005521,0,lca}; +Point(104) = {0.002219,0.008223,0,lca}; +Point(105) = {0.003943,0.010884,0,lca}; +Point(106) = {0.006156,0.013503,0,lca}; +Point(107) = {0.008856,0.016078,0,lca}; +Point(108) = {0.012042,0.018607,0,lca}; +Point(109) = {0.015708,0.021088,0,lca}; +Point(110) = {0.019853,0.023517,0,lca}; +Point(111) = {0.024472,0.025893,0,lca}; +Point(112) = {0.029560,0.028212,0,lca}; +Point(113) = {0.035112,0.030471,0,lca}; +Point(114) = {0.041123,0.032668,0,lca}; +Point(115) = {0.047586,0.034800,0,lca}; +Point(116) = {0.054497,0.036863,0,lca}; +Point(117) = {0.061847,0.038854,0,lca}; +Point(118) = {0.069629,0.040770,0,lca}; +Point(119) = {0.077836,0.042608,0,lca}; +Point(120) = {0.086460,0.044364,0,lca}; +Point(121) = {0.095492,0.046037,0,lca}; +Point(122) = {0.104922,0.047624,0,lca}; +Point(123) = {0.114743,0.049121,0,lca}; +Point(124) = {0.124944,0.050527,0,lca}; +Point(125) = {0.135516,0.051839,0,lca}; +Point(126) = {0.146447,0.053056,0,lca}; +Point(127) = {0.157726,0.054176,0,lca}; +Point(128) = {0.169344,0.055197,0,lca}; +Point(129) = {0.181288,0.056119,0,lca}; +Point(130) = {0.193546,0.056940,0,lca}; +Point(131) = {0.206107,0.057661,0,lca}; +Point(132) = {0.218958,0.058280,0,lca}; +Point(133) = {0.232087,0.058799,0,lca}; +Point(134) = {0.245479,0.059217,0,lca}; +Point(135) = {0.259123,0.059535,0,lca}; +Point(136) = {0.273005,0.059754,0,lca}; +Point(137) = {0.287110,0.059876,0,lca}; +Point(138) = {0.301426,0.059902,0,lca}; +Point(139) = {0.315938,0.059834,0,lca}; +Point(140) = {0.330631,0.059674,0,lca}; +Point(141) = {0.345492,0.059424,0,lca}; +Point(142) = {0.360504,0.059087,0,lca}; +Point(143) = {0.375655,0.058666,0,lca}; +Point(144) = {0.390928,0.058163,0,lca}; +Point(145) = {0.406309,0.057581,0,lca}; +Point(146) = {0.421783,0.056924,0,lca}; +Point(147) = {0.437333,0.056195,0,lca}; +Point(148) = {0.452946,0.055397,0,lca}; +Point(149) = {0.468605,0.054534,0,lca}; +Point(150) = {0.484295,0.053608,0,lca}; +Point(151) = {0.500000,0.052625,0,lca}; +Point(152) = {0.515705,0.051587,0,lca}; +Point(153) = {0.531395,0.050499,0,lca}; +Point(154) = {0.547054,0.049362,0,lca}; +Point(155) = {0.562667,0.048182,0,lca}; +Point(156) = {0.578217,0.046962,0,lca}; +Point(157) = {0.593691,0.045705,0,lca}; +Point(158) = {0.609072,0.044414,0,lca}; +Point(159) = {0.624345,0.043094,0,lca}; +Point(160) = {0.639496,0.041747,0,lca}; +Point(161) = {0.654508,0.040378,0,lca}; +Point(162) = {0.669369,0.038988,0,lca}; +Point(163) = {0.684062,0.037582,0,lca}; +Point(164) = {0.698574,0.036163,0,lca}; +Point(165) = {0.712890,0.034733,0,lca}; +Point(166) = {0.726995,0.033296,0,lca}; +Point(167) = {0.740877,0.031856,0,lca}; +Point(168) = {0.754521,0.030414,0,lca}; +Point(169) = {0.767913,0.028974,0,lca}; +Point(170) = {0.781042,0.027539,0,lca}; +Point(171) = {0.793893,0.026111,0,lca}; +Point(172) = {0.806454,0.024694,0,lca}; +Point(173) = {0.818712,0.023291,0,lca}; +Point(174) = {0.830656,0.021904,0,lca}; +Point(175) = {0.842274,0.020535,0,lca}; +Point(176) = {0.853553,0.019189,0,lca}; +Point(177) = {0.864484,0.017868,0,lca}; +Point(178) = {0.875056,0.016574,0,lca}; +Point(179) = {0.885257,0.015310,0,lca}; +Point(180) = {0.895078,0.014079,0,lca}; +Point(181) = {0.904508,0.012883,0,lca}; +Point(182) = {0.913540,0.011726,0,lca}; +Point(183) = {0.922164,0.010610,0,lca}; +Point(184) = {0.930371,0.009537,0,lca}; +Point(185) = {0.938153,0.008510,0,lca}; +Point(186) = {0.945503,0.007531,0,lca}; +Point(187) = {0.952414,0.006603,0,lca}; +Point(188) = {0.958877,0.005729,0,lca}; +Point(189) = {0.964888,0.004909,0,lca}; +Point(190) = {0.970440,0.004147,0,lca}; +Point(191) = {0.975528,0.003443,0,lca}; +Point(192) = {0.980147,0.002801,0,lca}; +Point(193) = {0.984292,0.002222,0,lca}; +Point(194) = {0.987958,0.001707,0,lca}; +Point(195) = {0.991144,0.001258,0,lca}; +Point(196) = {0.993844,0.000876,0,lca}; +Point(197) = {0.996057,0.000562,0,lca}; +Point(198) = {0.997781,0.000317,0,lca}; +Point(199) = {0.999013,0.000141,0,lca}; +Point(200) = {0.999753,0.000035,0,lca}; + +//Points numerotation: +numberLeadingEgde = 101 ; +numberLowerSurface = 81 ; +numberUpperSurface = 121 ; + +//Distances: +distanceTrailingLowerPoint = 0.908262 ; +distanceLowerUpperPoint = 0.222905 ; +distanceUpperTrailingPoint = 0.908262 ; + +Line(1) = { 1 ... 81 }; +Line(2) = { 81 ... 101 }; +Line(3) = { 101 ... 121 }; +Line(4) = { 121 ... 200, 1 }; + +Rotate { {0,0,1}, {1,0,0}, Incidence } { Line { 1 ... 4 } ; } + +/* Line Loop(1) = {1,2,3,4}; */ +/* Plane Surface(1) = {1}; */ diff --git a/Thermics/brick.geo b/Thermics/brick.geo index 3b56f06..0dbaa0e 100644 --- a/Thermics/brick.geo +++ b/Thermics/brick.geo @@ -1,111 +1,111 @@ -/* ------------------------------------------------------------------- - File "brick.geo" - - This file is the geometrical description used by GMSH to produce - the file "brick.msh". - ------------------------------------------------------------------- */ - -/* Gmsh options can be set directly in the .geo file. - Setting "Solver.AutoMesh" to 2 ensures that GMSH systematically - regenerates the mesh at each model execution, and does not reuse - the mesh on disk if it exists (which is the default option). - This option is needed in this model, because the interactive - model parameters "Flag_Regularization" has an effect - on the definition of the regions, which makes remeshing mandatory. */ - -Solver.AutoMesh = 2; - -Include "brick_common.pro"; - -/* The (very) simple geometry of this thermal model only contains - rectangles. It is the opportunity to illustrate - the function definition capabilities of Gmsh. */ - -Function Def_Rectangle -p1=newp; Point(newp)={xc_, yc_, 0, lc_}; -p2=newp; Point(newp)={xc_+dx_, yc_, 0, lc_}; -p3=newp; Point(newp)={xc_+dx_, yc_+dy_, 0, lc_}; -p4=newp; Point(newp)={xc_, yc_+dy_, 0, lc_}; - -l1=newl; Line(newl)={p1,p2}; -l2=newl; Line(newl)={p2,p3}; -l3=newl; Line(newl)={p3,p4}; -l4=newl; Line(newl)={p4,p1}; - -lines_[] = {l1, l2, l3, l4}; - -ll1 = newll; Line Loop(ll1) = {lines_[]}; -s_ = news; Plane Surface(news) = {ll1, ll_Holes_[]}; -Return // end of Function Def_Rectangle - -/* Note that the code above is not parsed before it is called. - Good practice for readability (but by no means mandatory) - is to distinguish function variables from other variables. - This is done here with a trailing "_" in the variable name. */ - - -// Window 1 (with optional layer of thickness "e_layer") -dx_ = dx_Win1; -dy_ = dy_Win1; -lc_ = lc_Win1; -xc_ = xc_Win1-dx_/2; yc_=yc_Win1-dy_/2; -ll_Holes_[]={}; -Call Def_Rectangle; -s_Win1 = s_; -l_Win1[] = lines_[]; - -If( !Flag_Regularization ) - ll_HolesForBrick[] += ll1; -Else - ll_HolesForLayer[] += ll1; - dx_ = dx_Win1+2*e_layer; - dy_ = dy_Win1+2*e_layer; - lc_ = lc_Win1; - xc_ = xc_Win1-dx_/2; yc_=yc_Win1-dy_/2; - - ll_Holes_[] = {ll_HolesForLayer[]}; - Call Def_Rectangle; - s_Win1_Layer = s_; - l_Win1_Layer[] = lines_[]; - ll_HolesForBrick[] += ll1; -EndIf - -// Window 2 -dx_ = dx_Win2; -dy_ = dy_Win2; -lc_ = lc_Win2; -xc_ = xc_Win2-dx_/2; yc_=yc_Win2-dy_/2; -ll_Holes_[]={}; -Call Def_Rectangle; -s_Win2 = s_; -l_Win2[] = lines_[]; -ll_HolesForBrick[] += ll1; - -// Brick -dx_ = dx_Brick; dy_ = dy_Brick; -lc_ = lc_Brick; -xc_ = 0; yc_ = 0; -ll_Holes_[] = {ll_HolesForBrick[]}; -Call Def_Rectangle; -s_Brick = s_; -l_Brick[] = lines_[]; - -//Printf("l_Brick", l_Brick[]); - - -// Physical regions - -Physical Surface("Brick", 100) = {s_Brick}; -Physical Surface("Window1", 111) = {s_Win1}; -Physical Surface("Window2", 112) = {s_Win2}; -If( Flag_Regularization ) - Physical Surface("LayerWindow1", 115) = {s_Win1_Layer}; -EndIf - -Physical Line("Surface1", 201) = { l_Brick[{3}] }; -Physical Line("Surface2", 202) = { l_Brick[{1}] }; -Physical Line("Surface3", 203) = { l_Brick[{0}], l_Brick[{2}] }; - -Physical Line("SurfWindow1", 211) = {l_Win1[]}; -Physical Line("SurfWindow2", 212) = {l_Win2[]}; - +/* ------------------------------------------------------------------- + File "brick.geo" + + This file is the geometrical description used by GMSH to produce + the file "brick.msh". + ------------------------------------------------------------------- */ + +/* Gmsh options can be set directly in the .geo file. + Setting "Solver.AutoMesh" to 2 ensures that GMSH systematically + regenerates the mesh at each model execution, and does not reuse + the mesh on disk if it exists (which is the default option). + This option is needed in this model, because the interactive + model parameters "Flag_Regularization" has an effect + on the definition of the regions, which makes remeshing mandatory. */ + +Solver.AutoMesh = 2; + +Include "brick_common.pro"; + +/* The (very) simple geometry of this thermal model only contains + rectangles. It is the opportunity to illustrate + the function definition capabilities of Gmsh. */ + +Function Def_Rectangle +p1=newp; Point(newp)={xc_, yc_, 0, lc_}; +p2=newp; Point(newp)={xc_+dx_, yc_, 0, lc_}; +p3=newp; Point(newp)={xc_+dx_, yc_+dy_, 0, lc_}; +p4=newp; Point(newp)={xc_, yc_+dy_, 0, lc_}; + +l1=newl; Line(newl)={p1,p2}; +l2=newl; Line(newl)={p2,p3}; +l3=newl; Line(newl)={p3,p4}; +l4=newl; Line(newl)={p4,p1}; + +lines_[] = {l1, l2, l3, l4}; + +ll1 = newll; Line Loop(ll1) = {lines_[]}; +s_ = news; Plane Surface(news) = {ll1, ll_Holes_[]}; +Return // end of Function Def_Rectangle + +/* Note that the code above is not parsed before it is called. + Good practice for readability (but by no means mandatory) + is to distinguish function variables from other variables. + This is done here with a trailing "_" in the variable name. */ + + +// Window 1 (with optional layer of thickness "e_layer") +dx_ = dx_Win1; +dy_ = dy_Win1; +lc_ = lc_Win1; +xc_ = xc_Win1-dx_/2; yc_=yc_Win1-dy_/2; +ll_Holes_[]={}; +Call Def_Rectangle; +s_Win1 = s_; +l_Win1[] = lines_[]; + +If( !Flag_Regularization ) + ll_HolesForBrick[] += ll1; +Else + ll_HolesForLayer[] += ll1; + dx_ = dx_Win1+2*e_layer; + dy_ = dy_Win1+2*e_layer; + lc_ = lc_Win1; + xc_ = xc_Win1-dx_/2; yc_=yc_Win1-dy_/2; + + ll_Holes_[] = {ll_HolesForLayer[]}; + Call Def_Rectangle; + s_Win1_Layer = s_; + l_Win1_Layer[] = lines_[]; + ll_HolesForBrick[] += ll1; +EndIf + +// Window 2 +dx_ = dx_Win2; +dy_ = dy_Win2; +lc_ = lc_Win2; +xc_ = xc_Win2-dx_/2; yc_=yc_Win2-dy_/2; +ll_Holes_[]={}; +Call Def_Rectangle; +s_Win2 = s_; +l_Win2[] = lines_[]; +ll_HolesForBrick[] += ll1; + +// Brick +dx_ = dx_Brick; dy_ = dy_Brick; +lc_ = lc_Brick; +xc_ = 0; yc_ = 0; +ll_Holes_[] = {ll_HolesForBrick[]}; +Call Def_Rectangle; +s_Brick = s_; +l_Brick[] = lines_[]; + +//Printf("l_Brick", l_Brick[]); + + +// Physical regions + +Physical Surface("Brick", 100) = {s_Brick}; +Physical Surface("Window1", 111) = {s_Win1}; +Physical Surface("Window2", 112) = {s_Win2}; +If( Flag_Regularization ) + Physical Surface("LayerWindow1", 115) = {s_Win1_Layer}; +EndIf + +Physical Line("Surface1", 201) = { l_Brick[{3}] }; +Physical Line("Surface2", 202) = { l_Brick[{1}] }; +Physical Line("Surface3", 203) = { l_Brick[{0}], l_Brick[{2}] }; + +Physical Line("SurfWindow1", 211) = {l_Win1[]}; +Physical Line("SurfWindow2", 212) = {l_Win2[]}; + diff --git a/Thermics/brick.pro b/Thermics/brick.pro index 78ca76c..3f1065b 100644 --- a/Thermics/brick.pro +++ b/Thermics/brick.pro @@ -1,420 +1,420 @@ -/* ------------------------------------------------------------------- - Tutorial 5 : thermal problem with contact resistances - - Features: - - Contact resistances: scalar FunctionSpace with a surface discontinuity - - Region with a uniform temperature (infinite thermal conductivity) - - Computation of the heat flux through surfaces - - Import a source field from a file - - To compute the solution in a terminal: - getdp brick.pro -solve Thermal_T -pos Map_T - - To compute the solution interactively from the Gmsh GUI: - File > Open > brick.pro - Run (button at the bottom of the left panel) - ------------------------------------------------------------------- */ - -/* This model is a rectangular brick with two windows, where various kinds of - thermal constraints can be set. Dirichlet, Neumann and convection boundary - conditions are imposed on different parts of the surface of the brick. The - model is rather academic but it demonstrates some useful high-level GetDP - features. - - Governing eqations are - - div ( -lambda grad T ) = Q in Vol_The - -lambda grad T . n = qn = 0 on Sur_Neu_The - - Contact thermal resistance: - - First, it is shown how to implement contact thermal resistances with surface - elements. The surface elements are associated with a thickness and a thermal - conductivity (typically much lower than that of surrounding regions). The - implementation takes advantage of the powerful FunctionSpace definition in - GetDP. - - With the flag "Flag_Regularization", the contact surface can be, for the sake - of comparison, replaced by a thin volume conducting region. - - Thermal "electrode": - - The floating potential idea (introduced in tutorial 4) is reconsidered here - in a thermal context to represent a region with a very large thermal - conductivity where, consequently, the temperature field is uniform (exactly - like the electric potential is uniform on an electrode). The dual quantity - of this uniform temperature "T_electrode" [K] (which is the "associated - global quantity" in GetDP language) is the heat flux "Q_electrode" [W] - injected in the electrode by the agent that maintains the temperature equal - to the prescribed value. - - The value of Q_electrode is a by-product of the system resolution provided - the term - - GlobalTerm { [-Dof{Q_electrode} , {T_electrode} ] ; In Tfloating_The ; } - - is present in the "Resolution" section. This term triggers the writing in the - linear system of a supplementary equation associated with the global basis - function BF{T_electrode}. All integrations are automatically done by GetDP, - and the value of Q_electrode is obtained in postprocessing with the - PostOperation - - Print[ Q_electrode, OnRegion Tfloating_The, ... ] - - Heat flux through surfaces: - - The purpose of a thermal simulation usually goes beyond the mere calculation - of a temperature distribution. One is in general also interested in - evaluating the heat flux q(S) through some specific surface S: - - q(S) = ( -lambda grad T . n )_S - - This quantity cannot be computed from the temperature distribution available - on the surface S only. As heat flux is related with the gradient of - temperature in the direction normal to the surface, its computation relies on - the temperature distribution in a neighborhood of the surface. This means - that volume elements in contact with the considered surface need be involved - in the computation. To achieve this with getDP, a good method proceeds by - the definition a smooth auxiliary function g(S), with g(S)=1 on S, and g(S)=0 - outside a finite neighborhood of S. Typically, g(S) is the sum of the shape - functions of the nodes on S. Let w(S) be the support of g(S), and let dw(S) - denote the boundary of w(S). We then have, just adding and substracting - dw(S) to the surface of integration S - - q(S) = ( -lambda grad T . n g(S) )_{ dw(S) - ( dw(S)-S ) }. - - dw(S) being a boundary, Stokes theorem can be invoked and, after an - integration by part one ends up with - - q(S) = ( -lambda grad T . grad g(S) )_w(S) - - ( -lambda grad T . n g(S) )_{dw(S)-S}. - + ( Q g(S) )_w(S) - - Now, g(S) is zero on {dw(S)-S}, except maybe at some surface elements - adjacents to dS, but not in dS. The second terme vanishes then if either S - is closed, or adjacent to a homogeneous Neumann boundary condition. - - The third term also vanishes, except if a region with a nonzero heatsource Q - is in contact with the surface S. - - So we have nearly always the following practical formula to evaluate the heat - flux across a surface S, in terms of a well-chosen auxiliary scalar function - g(S). - - q(S) = ( -lambda grad T . grad g(S) )_{support of g(S)} - - Particular cases: - - For the heat flux through the boundary of a thermal electrode, one uses g(S) - = BF(T_electrode). Note that this heat flux is equal to Q_electrode in the - stationary case. This is the case for the heat flux through the boundary of - Window2 - - Auxiliary functions g(S) are also generated for the surfaces named - "Surface_i", i=1,2,3 in the model. Note that the flux computed through - Surface_3 is incorrect because this surface is not adjacent to surfaces with - homogeneous Neumann boundary conditions. */ - -Include "brick_common.pro"; - -QWindow1 = DefineNumber[1e3, Name "Window1/Heat source [W]"]; - -/* The user is given the choice of setting either the global temperature or the - global heat flux in Window2. Check how the variable "Flag_ConstraintWin2" is - used at different places to alter the model according to that choice and to - manage the visibility of related input and output data.*/ -QWindow2 = DefineNumber[1e3, Name "Window2/Heat source [W]", - Visible Flag_ConstraintWin2]; -TWindow2 = DefineNumber[50, Name "Window2/Temperature [degC]", - Visible !Flag_ConstraintWin2]; -outQWindow2 = DefineNumber[0, Name "Output/Q window 2 [degC]", - Visible !Flag_ConstraintWin2, Highlight "Ivory"]; -outTWindow2 = DefineNumber[0, Name "Output/T window 2 [degC]", - Visible Flag_ConstraintWin2, Highlight "Ivory"]; -ConvectionCoef = DefineNumber[1000, Name"Surface2/hconv", - Label "Convection coefficient [W/(m^2K)]"]; -T_Ambiance = DefineNumber[20, Name"Surface2/Ambiance temperature [degC]"]; -T_Dirichlet = DefineNumber[20, Name"Surface1/Imposed temperature [degC]"]; - -Group { - /* Geometrical regions: */ - Brick = Region[100]; - LayerWindow1 = Region[115]; - Window1 = Region[111]; - Window2 = Region[112]; - SurfWindow1 = Region[211]; - SurfWindow2 = Region[212]; - - Surface_1 = Region[201]; - Surface_2 = Region[202]; - Surface_3 = Region[203]; - NbSurface = 3; - - /* Abstract regions: - - Vol_The : volume regions with a thermal conductivity - Sur_Dir_The : non-homogeneous Dirichlet boundary condition surface - Sur_Neu_The : homogeneous Neumann boundary condition surface - Sur_Convection_The : convective surface q.n = h ( T-Tinf ) - Vol_Qsource_The : volume heat source regions - Tfloating_The : thermal electrodes - */ - - Vol_The = Region[ {Brick, Window1, Window2, LayerWindow1} ]; - Sur_Dir_The = Region[ Surface_1 ]; - Sur_Neu_The = Region[ Surface_3 ]; - Sur_Convection_The = Region[ Surface_2 ]; - - Vol_Qsource_The = Region[ Window1 ]; - Tfloating_The = Region[ Window2 ]; - - If( !Flag_Regularization ) - Vol_OneSide_The = Region[ Brick ]; - Sur_Tdisc_The = Region[ SurfWindow1 ]; - Else - Vol_OneSide_The = Region[ {} ]; - Sur_Tdisc_The = Region[ {} ]; - EndIf -} - -Function { - lambda_Brick = 50.; // steel - lambda[ Brick ] = lambda_Brick; - lambda[ Region[ {Window1, Window2} ] ] = lambda_Brick ; // comment - - lambda_Layer = 1.0; // 50 time smaller than surrounding regions - If( Flag_Regularization ) - lambda[ LayerWindow1 ] = lambda_Layer; - EndIf - lambda[ Sur_Tdisc_The ] = lambda_Layer; - thickness[ Sur_Tdisc_The ] = e_layer; - - h[ Surface_2 ] = ConvectionCoef; - Tinf[ Surface_2 ] = T_Ambiance; - - If( Flag_QFromFile ) - Qsource[ Window1 ] = ScalarField[XYZ[],0,1]{1}; - Else - Qsource[ Window1 ] = 0*QWindow1/SurfaceArea[]; - EndIf -} - -Constraint { - { Name Dirichlet_The ; - Case { - { Region Sur_Dir_The ; Value T_Dirichlet ; } - } - } - { Name T_Discontinuity ; - Case { - { Region SurfWindow1 ; Value 20 ; } - } - } - { Name T_electrode; - Case { - If( !Flag_ConstraintWin2 ) - { Region Window2 ; Value TWindow2 ; } - EndIf - } - } - { Name Q_electrode; - Case { - If( Flag_ConstraintWin2 ) - { Region Window2 ; Value QWindow2 ; } - EndIf - } - } - For i In {1:NbSurface} - { Name FluxLayer~{i} ; - Case { - { Region Surface~{i} ; Value 1. ; } - } - } - EndFor -} - -Integration { - { Name Int ; - Case { - { Type Gauss ; - Case { - { GeoElement Triangle ; NumberOfPoints 4 ; } - { GeoElement Quadrangle ; NumberOfPoints 4 ; } - { GeoElement Line ; NumberOfPoints 4 ; } - } - } - } - } -} - -Jacobian { - { Name Vol ; - Case { - { Region All ; Jacobian Vol ; } - } - } - { Name Sur ; - Case { - { Region All ; Jacobian Sur ; } - } - } -} - -Group { - Dom_Hgrad_T = Region[ {Vol_The, Sur_Convection_The, Sur_Tdisc_The} ]; - DomainWithSurf_TL_The = - ElementsOf[ {Vol_OneSide_The, Sur_Tdisc_The}, OnOneSideOf Sur_Tdisc_The ]; -} - -FunctionSpace { - { Name Hgrad_T; Type Form0 ; - BasisFunction { - { Name sn ; NameOfCoef Tn ; Function BF_Node ; - Support Dom_Hgrad_T ; - Entity NodesOf[All, Not Tfloating_The] ; } - { Name sf ; NameOfCoef Tf ; Function BF_GroupOfNodes ; - Support Dom_Hgrad_T ; Entity GroupsOfNodesOf[ Tfloating_The ] ; } - { Name sdn ; NameOfCoef Tdn ; Function BF_Node ; - Support DomainWithSurf_TL_The ; Entity NodesOf[ Sur_Tdisc_The ] ; } - } - SubSpace { - { Name Tcont ; NameOfBasisFunction { sn, sf } ; } - { Name Tdisc ; NameOfBasisFunction { sdn } ; } - } - GlobalQuantity { - { Name T_electrode ; Type AliasOf ; NameOfCoef Tf ; } - { Name Q_electrode ; Type AssociatedWith ; NameOfCoef Tf ; } - } - Constraint { - { NameOfCoef Tn ; EntityType NodesOf ; - NameOfConstraint Dirichlet_The ; } - // { NameOfCoef Tdn ; EntityType NodesOf ; // - // NameOfConstraint T_Discontinuity ; } // - { NameOfCoef T_electrode ; EntityType GroupsOfNodesOf ; - NameOfConstraint T_electrode ; } - { NameOfCoef Q_electrode ; EntityType GroupsOfNodesOf ; - NameOfConstraint Q_electrode ; } - } - } - For i In {1:NbSurface} - { Name FluxLayer~{i} ; Type Form0 ; - BasisFunction { - { Name gn ; NameOfCoef un ; Function BF_GroupOfNodes; - Support Dom_Hgrad_T ; Entity GroupsOfNodesOf[ Surface~{i} ] ; } - } - Constraint { - { NameOfCoef un ; EntityType GroupsOfNodesOf ; - NameOfConstraint FluxLayer~{i} ; } - } - } - EndFor -} - -Formulation { - { Name Thermal_T ; Type FemEquation ; - Quantity { - { Name T ; Type Local ; NameOfSpace Hgrad_T ; } - { Name Tcont ; Type Local ; NameOfSpace Hgrad_T[Tcont] ; } - { Name Tdisc ; Type Local ; NameOfSpace Hgrad_T[Tdisc] ; } - { Name Tglob ; Type Global ; NameOfSpace Hgrad_T[T_electrode] ; } - { Name Qglob ; Type Global ; NameOfSpace Hgrad_T[Q_electrode] ; } - For i In {1:NbSurface} - { Name un~{i} ; Type Local ; NameOfSpace FluxLayer~{i} ; } - EndFor - } - Equation { - Integral { [ lambda[] * Dof{d T} , {d T} ] ; - In Vol_The; Integration Int ; Jacobian Vol ; } - - Integral { [ ( lambda[]/thickness[] ) * Dof{Tdisc} , {Tdisc} ] ; - In Sur_Tdisc_The; Integration Int ; Jacobian Sur ; } - - Integral { [ -Qsource[] , {T} ] ; - In Vol_Qsource_The ; Integration Int ; Jacobian Vol ; } - - Integral { [ h[] * Dof{T} , {T} ] ; - In Sur_Convection_The ; Integration Int ; Jacobian Sur ; } - - Integral { [ -h[] * Tinf[] , {T} ] ; - In Sur_Convection_The ; Integration Int ; Jacobian Sur ; } - - GlobalTerm { [-Dof{Qglob} , {Tglob} ] ; In Tfloating_The ; } - - For i In {1:NbSurface} - Integral { [ 0 * Dof{un~{i}} , {un~{i}} ] ; - In Vol_The ; Integration Int ; Jacobian Vol ; } - EndFor - } - } -} - -Resolution { - { Name Thermal_T ; - System { - { Name Sys_The ; NameOfFormulation Thermal_T ; } - } - Operation { - If( Flag_QFromFile ) - GmshRead[ "Q.pos", 1]; - EndIf - DeleteFile["output.txt"]; - Generate Sys_The ; Solve Sys_The ; SaveSolution Sys_The ; - } - } -} - -PostProcessing { - { Name Thermal_T ; NameOfFormulation Thermal_T ; - PostQuantity { - { Name T ; Value { Term { [ {T} ] ; - In Dom_Hgrad_T ; Jacobian Vol ; } } } - { Name q ; Value { Term { [ -lambda[] * {d T} ] ; - In Dom_Hgrad_T ; Jacobian Vol ; } } } - { Name Tcont ; Value { Term { [ {Tcont} ] ; - In Dom_Hgrad_T ; Jacobian Vol ; } } } - { Name Tdisc ; Value { Term { [ {Tdisc} ] ; - In Dom_Hgrad_T ; Jacobian Vol ; } } } - { Name Qglob; Value { Term { [ {Qglob} ]; In Tfloating_The; } } } - { Name Tglob; Value { Term { [ {Tglob} ]; In Tfloating_The; } } } - - For i In {1:NbSurface} - { Name un~{i} ; Value { Local { [ {un~{i}} ] ; - In Vol_The ; Jacobian Vol ; } } } - { Name IFlux~{i} ; Value { Integral { [ -lambda[]*{d T} * {d un~{i}} ]; - In Vol_The ; Jacobian Vol ; Integration Int ; } } } - EndFor - - } - } -} - -PostOperation Map_T UsingPost Thermal_T { - If( !Flag_Regularization ) - Print[ Tcont, OnElementsOf Vol_The, File "Tcont.pos"] ; - Print[ Tdisc, OnElementsOf Vol_The, File "Tdisc.pos"] ; - EndIf - - If(Flag_ConstraintWin2) - Print[ Tglob, OnRegion Tfloating_The, File > "output.txt", Color "Ivory", - Format Table, SendToServer "Output/T window 2 [degC]" ]; - Else - Print[ Qglob, OnRegion Tfloating_The, File > "output.txt", Color "Ivory", - Format Table, SendToServer "Output/Q window 2 [degC]" ]; - EndIf - - For i In {1:NbSurface} - Print[un~{i}, OnElementsOf Vol_The, - File Sprintf("FluxLayer_%g.pos",i)]; - Print[ IFlux~{i}[Vol_The], OnGlobal, - Format TimeTable, File > "Fluxes.dat", Color "Ivory", - SendToServer Sprintf("Output/Heat flux surface %g [W]", i)]; - EndFor - Print[ T, OnElementsOf Vol_The, File "T.pos" ] ; - Echo[ StrCat["l=PostProcessing.NbViews-1;", - "View[l].IntervalsType = 3;", - "View[l].NbIso = 30;", - "View[l].NormalRaise = 0.0005;"], - File "tmp.geo", LastTimeStepOnly] ; - Print [ q, OnLine {{0.02,0.0001,0}{0.02,0.05,0}} {200}, - Format SimpleTable, File "Cut.txt" ]; -} +/* ------------------------------------------------------------------- + Tutorial 5 : thermal problem with contact resistances + + Features: + - Contact resistances: scalar FunctionSpace with a surface discontinuity + - Region with a uniform temperature (infinite thermal conductivity) + - Computation of the heat flux through surfaces + - Import a source field from a file + + To compute the solution in a terminal: + getdp brick.pro -solve Thermal_T -pos Map_T + + To compute the solution interactively from the Gmsh GUI: + File > Open > brick.pro + Run (button at the bottom of the left panel) + ------------------------------------------------------------------- */ + +/* This model is a rectangular brick with two windows, where various kinds of + thermal constraints can be set. Dirichlet, Neumann and convection boundary + conditions are imposed on different parts of the surface of the brick. The + model is rather academic but it demonstrates some useful high-level GetDP + features. + + Governing eqations are + + div ( -lambda grad T ) = Q in Vol_The + -lambda grad T . n = qn = 0 on Sur_Neu_The + + Contact thermal resistance: + + First, it is shown how to implement contact thermal resistances with surface + elements. The surface elements are associated with a thickness and a thermal + conductivity (typically much lower than that of surrounding regions). The + implementation takes advantage of the powerful FunctionSpace definition in + GetDP. + + With the flag "Flag_Regularization", the contact surface can be, for the sake + of comparison, replaced by a thin volume conducting region. + + Thermal "electrode": + + The floating potential idea (introduced in tutorial 4) is reconsidered here + in a thermal context to represent a region with a very large thermal + conductivity where, consequently, the temperature field is uniform (exactly + like the electric potential is uniform on an electrode). The dual quantity + of this uniform temperature "T_electrode" [K] (which is the "associated + global quantity" in GetDP language) is the heat flux "Q_electrode" [W] + injected in the electrode by the agent that maintains the temperature equal + to the prescribed value. + + The value of Q_electrode is a by-product of the system resolution provided + the term + + GlobalTerm { [-Dof{Q_electrode} , {T_electrode} ] ; In Tfloating_The ; } + + is present in the "Resolution" section. This term triggers the writing in the + linear system of a supplementary equation associated with the global basis + function BF{T_electrode}. All integrations are automatically done by GetDP, + and the value of Q_electrode is obtained in postprocessing with the + PostOperation + + Print[ Q_electrode, OnRegion Tfloating_The, ... ] + + Heat flux through surfaces: + + The purpose of a thermal simulation usually goes beyond the mere calculation + of a temperature distribution. One is in general also interested in + evaluating the heat flux q(S) through some specific surface S: + + q(S) = ( -lambda grad T . n )_S + + This quantity cannot be computed from the temperature distribution available + on the surface S only. As heat flux is related with the gradient of + temperature in the direction normal to the surface, its computation relies on + the temperature distribution in a neighborhood of the surface. This means + that volume elements in contact with the considered surface need be involved + in the computation. To achieve this with getDP, a good method proceeds by + the definition a smooth auxiliary function g(S), with g(S)=1 on S, and g(S)=0 + outside a finite neighborhood of S. Typically, g(S) is the sum of the shape + functions of the nodes on S. Let w(S) be the support of g(S), and let dw(S) + denote the boundary of w(S). We then have, just adding and substracting + dw(S) to the surface of integration S + + q(S) = ( -lambda grad T . n g(S) )_{ dw(S) - ( dw(S)-S ) }. + + dw(S) being a boundary, Stokes theorem can be invoked and, after an + integration by part one ends up with + + q(S) = ( -lambda grad T . grad g(S) )_w(S) + - ( -lambda grad T . n g(S) )_{dw(S)-S}. + + ( Q g(S) )_w(S) + + Now, g(S) is zero on {dw(S)-S}, except maybe at some surface elements + adjacents to dS, but not in dS. The second terme vanishes then if either S + is closed, or adjacent to a homogeneous Neumann boundary condition. + + The third term also vanishes, except if a region with a nonzero heatsource Q + is in contact with the surface S. + + So we have nearly always the following practical formula to evaluate the heat + flux across a surface S, in terms of a well-chosen auxiliary scalar function + g(S). + + q(S) = ( -lambda grad T . grad g(S) )_{support of g(S)} + + Particular cases: + + For the heat flux through the boundary of a thermal electrode, one uses g(S) + = BF(T_electrode). Note that this heat flux is equal to Q_electrode in the + stationary case. This is the case for the heat flux through the boundary of + Window2 + + Auxiliary functions g(S) are also generated for the surfaces named + "Surface_i", i=1,2,3 in the model. Note that the flux computed through + Surface_3 is incorrect because this surface is not adjacent to surfaces with + homogeneous Neumann boundary conditions. */ + +Include "brick_common.pro"; + +QWindow1 = DefineNumber[1e3, Name "Window1/Heat source [W]"]; + +/* The user is given the choice of setting either the global temperature or the + global heat flux in Window2. Check how the variable "Flag_ConstraintWin2" is + used at different places to alter the model according to that choice and to + manage the visibility of related input and output data.*/ +QWindow2 = DefineNumber[1e3, Name "Window2/Heat source [W]", + Visible Flag_ConstraintWin2]; +TWindow2 = DefineNumber[50, Name "Window2/Temperature [degC]", + Visible !Flag_ConstraintWin2]; +outQWindow2 = DefineNumber[0, Name "Output/Q window 2 [degC]", + Visible !Flag_ConstraintWin2, Highlight "Ivory"]; +outTWindow2 = DefineNumber[0, Name "Output/T window 2 [degC]", + Visible Flag_ConstraintWin2, Highlight "Ivory"]; +ConvectionCoef = DefineNumber[1000, Name"Surface2/hconv", + Label "Convection coefficient [W/(m^2K)]"]; +T_Ambiance = DefineNumber[20, Name"Surface2/Ambiance temperature [degC]"]; +T_Dirichlet = DefineNumber[20, Name"Surface1/Imposed temperature [degC]"]; + +Group { + /* Geometrical regions: */ + Brick = Region[100]; + LayerWindow1 = Region[115]; + Window1 = Region[111]; + Window2 = Region[112]; + SurfWindow1 = Region[211]; + SurfWindow2 = Region[212]; + + Surface_1 = Region[201]; + Surface_2 = Region[202]; + Surface_3 = Region[203]; + NbSurface = 3; + + /* Abstract regions: + + Vol_The : volume regions with a thermal conductivity + Sur_Dir_The : non-homogeneous Dirichlet boundary condition surface + Sur_Neu_The : homogeneous Neumann boundary condition surface + Sur_Convection_The : convective surface q.n = h ( T-Tinf ) + Vol_Qsource_The : volume heat source regions + Tfloating_The : thermal electrodes + */ + + Vol_The = Region[ {Brick, Window1, Window2, LayerWindow1} ]; + Sur_Dir_The = Region[ Surface_1 ]; + Sur_Neu_The = Region[ Surface_3 ]; + Sur_Convection_The = Region[ Surface_2 ]; + + Vol_Qsource_The = Region[ Window1 ]; + Tfloating_The = Region[ Window2 ]; + + If( !Flag_Regularization ) + Vol_OneSide_The = Region[ Brick ]; + Sur_Tdisc_The = Region[ SurfWindow1 ]; + Else + Vol_OneSide_The = Region[ {} ]; + Sur_Tdisc_The = Region[ {} ]; + EndIf +} + +Function { + lambda_Brick = 50.; // steel + lambda[ Brick ] = lambda_Brick; + lambda[ Region[ {Window1, Window2} ] ] = lambda_Brick ; // comment + + lambda_Layer = 1.0; // 50 time smaller than surrounding regions + If( Flag_Regularization ) + lambda[ LayerWindow1 ] = lambda_Layer; + EndIf + lambda[ Sur_Tdisc_The ] = lambda_Layer; + thickness[ Sur_Tdisc_The ] = e_layer; + + h[ Surface_2 ] = ConvectionCoef; + Tinf[ Surface_2 ] = T_Ambiance; + + If( Flag_QFromFile ) + Qsource[ Window1 ] = ScalarField[XYZ[],0,1]{1}; + Else + Qsource[ Window1 ] = 0*QWindow1/SurfaceArea[]; + EndIf +} + +Constraint { + { Name Dirichlet_The ; + Case { + { Region Sur_Dir_The ; Value T_Dirichlet ; } + } + } + { Name T_Discontinuity ; + Case { + { Region SurfWindow1 ; Value 20 ; } + } + } + { Name T_electrode; + Case { + If( !Flag_ConstraintWin2 ) + { Region Window2 ; Value TWindow2 ; } + EndIf + } + } + { Name Q_electrode; + Case { + If( Flag_ConstraintWin2 ) + { Region Window2 ; Value QWindow2 ; } + EndIf + } + } + For i In {1:NbSurface} + { Name FluxLayer~{i} ; + Case { + { Region Surface~{i} ; Value 1. ; } + } + } + EndFor +} + +Integration { + { Name Int ; + Case { + { Type Gauss ; + Case { + { GeoElement Triangle ; NumberOfPoints 4 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } + { GeoElement Line ; NumberOfPoints 4 ; } + } + } + } + } +} + +Jacobian { + { Name Vol ; + Case { + { Region All ; Jacobian Vol ; } + } + } + { Name Sur ; + Case { + { Region All ; Jacobian Sur ; } + } + } +} + +Group { + Dom_Hgrad_T = Region[ {Vol_The, Sur_Convection_The, Sur_Tdisc_The} ]; + DomainWithSurf_TL_The = + ElementsOf[ {Vol_OneSide_The, Sur_Tdisc_The}, OnOneSideOf Sur_Tdisc_The ]; +} + +FunctionSpace { + { Name Hgrad_T; Type Form0 ; + BasisFunction { + { Name sn ; NameOfCoef Tn ; Function BF_Node ; + Support Dom_Hgrad_T ; + Entity NodesOf[All, Not Tfloating_The] ; } + { Name sf ; NameOfCoef Tf ; Function BF_GroupOfNodes ; + Support Dom_Hgrad_T ; Entity GroupsOfNodesOf[ Tfloating_The ] ; } + { Name sdn ; NameOfCoef Tdn ; Function BF_Node ; + Support DomainWithSurf_TL_The ; Entity NodesOf[ Sur_Tdisc_The ] ; } + } + SubSpace { + { Name Tcont ; NameOfBasisFunction { sn, sf } ; } + { Name Tdisc ; NameOfBasisFunction { sdn } ; } + } + GlobalQuantity { + { Name T_electrode ; Type AliasOf ; NameOfCoef Tf ; } + { Name Q_electrode ; Type AssociatedWith ; NameOfCoef Tf ; } + } + Constraint { + { NameOfCoef Tn ; EntityType NodesOf ; + NameOfConstraint Dirichlet_The ; } + // { NameOfCoef Tdn ; EntityType NodesOf ; // + // NameOfConstraint T_Discontinuity ; } // + { NameOfCoef T_electrode ; EntityType GroupsOfNodesOf ; + NameOfConstraint T_electrode ; } + { NameOfCoef Q_electrode ; EntityType GroupsOfNodesOf ; + NameOfConstraint Q_electrode ; } + } + } + For i In {1:NbSurface} + { Name FluxLayer~{i} ; Type Form0 ; + BasisFunction { + { Name gn ; NameOfCoef un ; Function BF_GroupOfNodes; + Support Dom_Hgrad_T ; Entity GroupsOfNodesOf[ Surface~{i} ] ; } + } + Constraint { + { NameOfCoef un ; EntityType GroupsOfNodesOf ; + NameOfConstraint FluxLayer~{i} ; } + } + } + EndFor +} + +Formulation { + { Name Thermal_T ; Type FemEquation ; + Quantity { + { Name T ; Type Local ; NameOfSpace Hgrad_T ; } + { Name Tcont ; Type Local ; NameOfSpace Hgrad_T[Tcont] ; } + { Name Tdisc ; Type Local ; NameOfSpace Hgrad_T[Tdisc] ; } + { Name Tglob ; Type Global ; NameOfSpace Hgrad_T[T_electrode] ; } + { Name Qglob ; Type Global ; NameOfSpace Hgrad_T[Q_electrode] ; } + For i In {1:NbSurface} + { Name un~{i} ; Type Local ; NameOfSpace FluxLayer~{i} ; } + EndFor + } + Equation { + Integral { [ lambda[] * Dof{d T} , {d T} ] ; + In Vol_The; Integration Int ; Jacobian Vol ; } + + Integral { [ ( lambda[]/thickness[] ) * Dof{Tdisc} , {Tdisc} ] ; + In Sur_Tdisc_The; Integration Int ; Jacobian Sur ; } + + Integral { [ -Qsource[] , {T} ] ; + In Vol_Qsource_The ; Integration Int ; Jacobian Vol ; } + + Integral { [ h[] * Dof{T} , {T} ] ; + In Sur_Convection_The ; Integration Int ; Jacobian Sur ; } + + Integral { [ -h[] * Tinf[] , {T} ] ; + In Sur_Convection_The ; Integration Int ; Jacobian Sur ; } + + GlobalTerm { [-Dof{Qglob} , {Tglob} ] ; In Tfloating_The ; } + + For i In {1:NbSurface} + Integral { [ 0 * Dof{un~{i}} , {un~{i}} ] ; + In Vol_The ; Integration Int ; Jacobian Vol ; } + EndFor + } + } +} + +Resolution { + { Name Thermal_T ; + System { + { Name Sys_The ; NameOfFormulation Thermal_T ; } + } + Operation { + If( Flag_QFromFile ) + GmshRead[ "Q.pos", 1]; + EndIf + DeleteFile["output.txt"]; + Generate Sys_The ; Solve Sys_The ; SaveSolution Sys_The ; + } + } +} + +PostProcessing { + { Name Thermal_T ; NameOfFormulation Thermal_T ; + PostQuantity { + { Name T ; Value { Term { [ {T} ] ; + In Dom_Hgrad_T ; Jacobian Vol ; } } } + { Name q ; Value { Term { [ -lambda[] * {d T} ] ; + In Dom_Hgrad_T ; Jacobian Vol ; } } } + { Name Tcont ; Value { Term { [ {Tcont} ] ; + In Dom_Hgrad_T ; Jacobian Vol ; } } } + { Name Tdisc ; Value { Term { [ {Tdisc} ] ; + In Dom_Hgrad_T ; Jacobian Vol ; } } } + { Name Qglob; Value { Term { [ {Qglob} ]; In Tfloating_The; } } } + { Name Tglob; Value { Term { [ {Tglob} ]; In Tfloating_The; } } } + + For i In {1:NbSurface} + { Name un~{i} ; Value { Local { [ {un~{i}} ] ; + In Vol_The ; Jacobian Vol ; } } } + { Name IFlux~{i} ; Value { Integral { [ -lambda[]*{d T} * {d un~{i}} ]; + In Vol_The ; Jacobian Vol ; Integration Int ; } } } + EndFor + + } + } +} + +PostOperation Map_T UsingPost Thermal_T { + If( !Flag_Regularization ) + Print[ Tcont, OnElementsOf Vol_The, File "Tcont.pos"] ; + Print[ Tdisc, OnElementsOf Vol_The, File "Tdisc.pos"] ; + EndIf + + If(Flag_ConstraintWin2) + Print[ Tglob, OnRegion Tfloating_The, File > "output.txt", Color "Ivory", + Format Table, SendToServer "Output/T window 2 [degC]" ]; + Else + Print[ Qglob, OnRegion Tfloating_The, File > "output.txt", Color "Ivory", + Format Table, SendToServer "Output/Q window 2 [degC]" ]; + EndIf + + For i In {1:NbSurface} + Print[un~{i}, OnElementsOf Vol_The, + File Sprintf("FluxLayer_%g.pos",i)]; + Print[ IFlux~{i}[Vol_The], OnGlobal, + Format TimeTable, File > "Fluxes.dat", Color "Ivory", + SendToServer Sprintf("Output/Heat flux surface %g [W]", i)]; + EndFor + Print[ T, OnElementsOf Vol_The, File "T.pos" ] ; + Echo[ StrCat["l=PostProcessing.NbViews-1;", + "View[l].IntervalsType = 3;", + "View[l].NbIso = 30;", + "View[l].NormalRaise = 0.0005;"], + File "tmp.geo", LastTimeStepOnly] ; + Print [ q, OnLine {{0.02,0.0001,0}{0.02,0.05,0}} {200}, + Format SimpleTable, File "Cut.txt" ]; +} diff --git a/Thermics/brick_common.pro b/Thermics/brick_common.pro index 4efa98e..09a999c 100644 --- a/Thermics/brick_common.pro +++ b/Thermics/brick_common.pro @@ -1,37 +1,37 @@ - -// Onelab parameters - -Flag_Regularization = - DefineNumber[0, Name "Options/Regularize field", Choices {0,1} ]; -Flag_QFromFile = - DefineNumber[0, Name "Options/Heat source from file", Choices {0,1} ]; -Flag_ConstraintWin2 = - DefineNumber[0, Name "Options/Constraint in Window2", - Choices {0="Fixed temperature", 1="Fixed heat flux"} ]; -MeshRefinement = - DefineNumber[1, Name "Options/0Mesh refinement", - Help "Choose 1 for a coarse mesh and 0.1 for a fine mesh."]; - -// Geometrical dimensions - -mm=1e-3; // mm to m conversion factor - -dx_Brick=100*mm; dy_Brick= 50*mm; -e_layer = 1*mm; -dx_Win1 = 20*mm; dy_Win1 = 20*mm; -If( Flag_Regularization ) - dx_Win1 += e_layer; - dy_Win1 += e_layer; -EndIf - -dx_Win2 = 20*mm; dy_Win2 = 20*mm; -xc_Win1 = 25*mm; yc_Win1 = dy_Brick/2; -xc_Win2 = 75*mm; yc_Win2 = dy_Brick/2; - -// Element sizes - -s=1; -lc_Brick = dy_Brick/20 *s; -lc_Win1 = dx_Win1/10 *s; -lc_Win2 = dx_Win2/10 *s; - + +// Onelab parameters + +Flag_Regularization = + DefineNumber[0, Name "Options/Regularize field", Choices {0,1} ]; +Flag_QFromFile = + DefineNumber[0, Name "Options/Heat source from file", Choices {0,1} ]; +Flag_ConstraintWin2 = + DefineNumber[0, Name "Options/Constraint in Window2", + Choices {0="Fixed temperature", 1="Fixed heat flux"} ]; +MeshRefinement = + DefineNumber[1, Name "Options/0Mesh refinement", + Help "Choose 1 for a coarse mesh and 0.1 for a fine mesh."]; + +// Geometrical dimensions + +mm=1e-3; // mm to m conversion factor + +dx_Brick=100*mm; dy_Brick= 50*mm; +e_layer = 1*mm; +dx_Win1 = 20*mm; dy_Win1 = 20*mm; +If( Flag_Regularization ) + dx_Win1 += e_layer; + dy_Win1 += e_layer; +EndIf + +dx_Win2 = 20*mm; dy_Win2 = 20*mm; +xc_Win1 = 25*mm; yc_Win1 = dy_Brick/2; +xc_Win2 = 75*mm; yc_Win2 = dy_Brick/2; + +// Element sizes + +s=1; +lc_Brick = dy_Brick/20 *s; +lc_Win1 = dx_Win1/10 *s; +lc_Win2 = dx_Win2/10 *s; + -- GitLab