[FEM] use magnetization constraint for 2D

- uses the constraint for 2D magnetodynamics to perform e.g. Elmer's tutorial non. 15

- modify the Material manager to get rid of magnetization but keep the vectorial functionality because in future there will be support for e.g. birefringence materials etc.
This commit is contained in:
Uwe
2023-02-09 15:20:26 +01:00
parent f6abb77758
commit a2ffadcb59
7 changed files with 68 additions and 77 deletions

View File

@@ -104,7 +104,7 @@ class MgDyn2Dwriter:
permittivity = round(permittivity, 20) # to get rid of numerical artifacts
self.write.constant("Permittivity Of Vacuum", permittivity)
def handleMagnetodynamic2DMaterial(self, bodies, equation):
def handleMagnetodynamic2DMaterial(self, bodies):
# check that all bodies have a set material
for name in bodies:
if self.write.getBodyMaterial(name) == None:
@@ -142,49 +142,60 @@ class MgDyn2Dwriter:
name, "Relative Permittivity",
float(m["RelativePermittivity"])
)
if "Magnetization1" in m:
magnetization = self.write.convert(m["Magnetization1"], "I/L")
def _outputMagnetodynamic2DBodyForce(self, obj, name, equation):
if hasattr(obj, "CurrentDensity"):
currentDensity = self.write.getFromUi(
obj.CurrentDensity.getValueAs("A/m^2"), "A/m^2", "I/L^2"
)
currentDensity = round(currentDensity, 10) # to get rid of numerical artifacts
if currentDensity == 0.0:
# a zero density would break Elmer
raise general_writer.WriteError("The current density must not be zero!")
self.write.bodyForce(name, "Current Density", currentDensity)
if hasattr(obj, "Magnetization_im_1"):
# output only if magnetization is enabled and needed
if not obj.Magnetization_re_1_Disabled:
if hasattr(obj, "Magnetization_re_1"):
magnetization = float(obj.Magnetization_re_1.getValueAs("A/m"))
self.write.material(name, "Magnetization 1", magnetization)
if "Magnetization2" in m:
magnetization = self.write.convert(m["Magnetization_2"], "I/L")
if not obj.Magnetization_re_2_Disabled:
if hasattr(obj, "Magnetization_re_2"):
magnetization = float(obj.Magnetization_re_2.getValueAs("A/m"))
self.write.material(name, "Magnetization 2", magnetization)
if "Magnetization3" in m:
magnetization = self.write.convert(m["Magnetization3"], "I/L")
if not obj.Magnetization_re_3_Disabled:
if hasattr(obj, "Magnetization_re_3"):
magnetization = float(obj.Magnetization_re_3.getValueAs("A/m"))
self.write.material(name, "Magnetization 3", magnetization)
if equation.IsHarmonic:
if "MagnetizationIm1" in m:
magnetization = self.write.convert(m["MagnetizationIm1"], "I/L")
# imaginaries are only needed for harmonic equation
if equation.IsHarmonic:
if not obj.Magnetization_im_1_Disabled:
if hasattr(obj, "Magnetization_im_1"):
magnetization = float(obj.Magnetization_im_1.getValueAs("A/m"))
self.write.material(name, "Magnetization Im 1", magnetization)
if "MagnetizationIm2" in m:
magnetization = self.write.convert(m["MagnetizationIm2"], "I/L")
if not obj.Magnetization_im_2_Disabled:
if hasattr(obj, "Magnetization_im_2"):
magnetization = float(obj.Magnetization_im_2.getValueAs("A/m"))
self.write.material(name, "Magnetization Im 2", magnetization)
if "MagnetizationIm3" in m:
magnetization = self.write.convert(m["MagnetizationIm3"], "I/L")
if not obj.Magnetization_im_3_Disabled:
if hasattr(obj, "Magnetization_im_3"):
magnetization = float(obj.Magnetization_im_3.getValueAs("A/m"))
self.write.material(name, "Magnetization Im 3", magnetization)
def _outputMagnetodynamic2DBodyForce(self, obj, name):
currentDensity = self.write.getFromUi(
obj.CurrentDensity.getValueAs("A/m^2"), "A/m^2", "I/L^2"
)
currentDensity = round(currentDensity, 10) # to get rid of numerical artifacts
if currentDensity == 0.0:
# a zero density would break Elmer
raise general_writer.WriteError("The current density must not be zero!")
self.write.bodyForce(name, "Current Density", currentDensity)
def handleMagnetodynamic2DBodyForces(self, bodies):
def handleMagnetodynamic2DBodyForces(self, bodies, equation):
currentDensities = self.write.getMember("Fem::ConstraintCurrentDensity")
for obj in currentDensities:
if obj.References:
for name in obj.References[0][1]:
self._outputMagnetodynamic2DBodyForce(obj, name)
self._outputMagnetodynamic2DBodyForce(obj, name, equation)
self.write.handled(obj)
else:
# if there is only one current density without a reference,
# add it to all bodies
if len(currentDensities) == 1:
for name in bodies:
self._outputMagnetodynamic2DBodyForce(obj, name)
self._outputMagnetodynamic2DBodyForce(obj, name, equation)
else:
raise general_writer.WriteError(
"Several current density constraints found without reference to a body.\n"
@@ -192,6 +203,25 @@ class MgDyn2Dwriter:
)
self.write.handled(obj)
magnetizations = self.write.getMember("Fem::ConstraintMagnetization")
for obj in magnetizations:
if obj.References:
for name in obj.References[0][1]:
self._outputMagnetodynamic2DBodyForce(obj, name, equation)
self.write.handled(obj)
else:
# if there is only one magnetization without a reference,
# add it to all bodies
if len(magnetizations) == 1:
for name in bodies:
self._outputMagnetodynamic2DBodyForce(obj, name, equation)
else:
raise general_writer.WriteError(
"Several magnetization constraints found without reference to a body.\n"
"Please set a body for each current density constraint."
)
self.write.handled(obj)
def handleMagnetodynamic2DBndConditions(self):
for obj in self.write.getMember("Fem::ConstraintElectrostaticPotential"):
if obj.References:

View File

@@ -564,8 +564,8 @@ class Writer(object):
if activeIn:
MgDyn2D.handleMagnetodynamic2DConstants()
MgDyn2D.handleMagnetodynamic2DBndConditions()
MgDyn2D.handleMagnetodynamic2DBodyForces(activeIn)
MgDyn2D.handleMagnetodynamic2DMaterial(activeIn, equation)
MgDyn2D.handleMagnetodynamic2DBodyForces(activeIn, equation)
MgDyn2D.handleMagnetodynamic2DMaterial(activeIn)
#-------------------------------------------------------------------------------------------
# Solver handling

View File

@@ -51,7 +51,7 @@ class _TaskPanel(object):
# magnetization is always a body force for 3D, therefore only allow solid
self._selectionWidget = selection_widgets.GeometryElementsSelection(
obj.References,
["Solid"],
["Solid", "Face"],
True,
False
)
@@ -128,17 +128,17 @@ class _TaskPanel(object):
self._paramWidget.imagZQSB).bind(self._obj, "Magnetization_im_3")
self._paramWidget.reXunspecBox.setChecked(
self._obj.Magnetization_re_1)
self._obj.Magnetization_re_1_Disabled)
self._paramWidget.reYunspecBox.setChecked(
self._obj.Magnetization_re_2)
self._obj.Magnetization_re_2_Disabled)
self._paramWidget.reZunspecBox.setChecked(
self._obj.Magnetization_re_3)
self._obj.Magnetization_re_3_Disabled)
self._paramWidget.imXunspecBox.setChecked(
self._obj.Magnetization_im_1)
self._obj.Magnetization_im_1_Disabled)
self._paramWidget.imYunspecBox.setChecked(
self._obj.Magnetization_im_2)
self._obj.Magnetization_im_2_Disabled)
self._paramWidget.imZunspecBox.setChecked(
self._obj.Magnetization_im_3)
self._obj.Magnetization_im_3_Disabled)
def _applyMagnetizationChanges(self, enabledBox, magnetizationQSB):
enabled = enabledBox.isChecked()

View File

@@ -682,15 +682,12 @@ def matProperWidget(parent=None, matproperty=None, Type="String", Value=None,
# for properties with an underscored number (vectorial values),
# we must strip the part after the first underscore to obtain the bound unit
# since in cardutils.py in def get_material_template
# the underscores were removed, we must first check for numbers
# and then for "Im" (denotes an imaginery value)
# the underscores were removed, we must check for numbers
import re
if re.search(r'\d', matproperty):
matpropertyNum = matproperty.rstrip('0123456789')
matproperty = matpropertyNum
if matproperty.find("Im") != -1:
matproperty = matproperty.split("Im")[0]
if hasattr(FreeCAD.Units, matproperty):
unit = getattr(FreeCAD.Units, matproperty)
quantity = FreeCAD.Units.Quantity(1, unit)

View File

@@ -123,15 +123,6 @@ ElectricalConductivity =
; https://en.wikipedia.org/wiki/Permeability_(electromagnetism)
RelativePermeability =
; The magnetization in [FreeCAD Magnetization unit]"
; https://en.wikipedia.org/wiki/Magnetization
Magnetization_1 =
Magnetization_2 =
Magnetization_3 =
Magnetization_Im_1 =
Magnetization_Im_2 =
Magnetization_Im_3 =
[Architectural]
; Description to be updated
Color =

View File

@@ -168,30 +168,6 @@
Type: 'Float'
URL: 'https://en.wikipedia.org/wiki/Permeability_(electromagnetism)'
Description: "The ratio to the permeability of the vacuum"
Magnetization_1:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization in x-direction in [FreeCAD Magnetization unit]"
Magnetization_2:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization in y-direction in [FreeCAD Magnetization unit]"
Magnetization_3:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization in z-direction in [FreeCAD Magnetization unit]"
Magnetization_Im_1:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization, imagaginary part, in x-direction in [FreeCAD Magnetization unit]"
Magnetization_Im_2:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization, imagaginary part, in y-direction in [FreeCAD Magnetization unit]"
Magnetization_Im_3:
Type: 'Quantity'
URL: 'https://en.wikipedia.org/wiki/Magnetization'
Description: "Magnetization, imagaginary part, in z-direction in [FreeCAD Magnetization unit]"
- Architectural:
Color:
Type: 'String'

View File

@@ -239,9 +239,6 @@ def get_material_template(withSpaces=False):
new_proper = re.sub(r"(\w)([A-Z]+)", r"\1 \2", proper)
# strip underscores of vectorial properties
new_proper = new_proper.replace("_", " ")
# this can lead to double spaces for imaginary properties
# e.g. "_Im_1", therefore remove one
new_proper = new_proper.replace(" ", " ")
new_group[gg][new_proper] = group[gg][proper]
new_template.append(new_group)
template_data = new_template