From 35725769d91d77115cef815b9f313ee1fa8984cb Mon Sep 17 00:00:00 2001 From: Uwe Date: Wed, 22 Feb 2023 03:07:12 +0100 Subject: [PATCH] [FEM] add example for magnetodynamic equation - also fix description of other recently added examples --- src/Mod/Fem/CMakeLists.txt | 1 + .../Fem/femexamples/equation_flow_elmer_2D.py | 2 +- .../Fem/femexamples/equation_flux_elmer.py | 2 +- .../equation_magnetodynamics_elmer.py | 235 ++++++++++++++++++ src/Mod/Fem/femexamples/manager.py | 2 + 5 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index a0ea837341..c07b5c5dea 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -79,6 +79,7 @@ SET(FemExamples_SRCS femexamples/equation_electrostatics_electricforce_elmer_nongui6.py femexamples/equation_flow_elmer_2D.py femexamples/equation_flux_elmer.py + femexamples/equation_magnetodynamics_elmer.py femexamples/frequency_beamsimple.py femexamples/manager.py femexamples/material_multiple_bendingbeam_fiveboxes.py diff --git a/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py b/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py index 60b8bd5bb0..09ef695b31 100644 --- a/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py +++ b/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py @@ -54,7 +54,7 @@ To run the example from Python console use: from femexamples.equation_flow_elmer_2D import setup setup() -Flow and Heat equation in FreeCAD FEM-Elmer +Flow and Heat equation - Elmer solver """ diff --git a/src/Mod/Fem/femexamples/equation_flux_elmer.py b/src/Mod/Fem/femexamples/equation_flux_elmer.py index 4cc27c3f9b..d8ed5dbf9c 100644 --- a/src/Mod/Fem/femexamples/equation_flux_elmer.py +++ b/src/Mod/Fem/femexamples/equation_flux_elmer.py @@ -49,7 +49,7 @@ To run the example from Python console use: from femexamples.equation_flux_elmer import setup setup() -Flow and Heat equation in FreeCAD FEM-Elmer +Potential flux and heat flux - Elmer solver """ diff --git a/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py b/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py new file mode 100644 index 0000000000..8326426115 --- /dev/null +++ b/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py @@ -0,0 +1,235 @@ +# *************************************************************************** +# * Copyright (c) 2023 Uwe Stöhr * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +import sys +import FreeCAD +from FreeCAD import Rotation +from FreeCAD import Vector + +import Fem +import ObjectsFem + +from BOPTools import SplitFeatures +from BasicShapes import Shapes +from . import manager +from .manager import get_meshname +from .manager import init_doc + +def get_information(): + return { + "name": "Magnetic Field Around Wire", + "meshtype": "solid", + "meshelement": "Tet10", + "constraints": ["electrostatic potential", "magnetization"], + "solvers": ["elmer"], + "material": "solid", + "equations": ["magnetodynamic"] + } + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.equation_magnetodynamics_elmer import setup +setup() + +Magnetodynamic equation - Elmer solver + +""" + +def setup(doc=None, solvertype="elmer"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # geometric objects + + # wire + Wire = doc.addObject("Part::Cylinder", "Wire") + Wire.Radius = "1 mm" + Wire.Height = "10 mm" + Wire.ViewObject.Visibility = False + + # air around wire + Air = Shapes.addTube(doc, "Tube") + Air.Label = "AirObject" + Air.OuterRadius = "5 mm" + Air.InnerRadius = "1 mm" + Air.Height = "10 mm" + Air.ViewObject.Visibility = False + + # BooleanFregments object to combine cut with rod + BooleanFragments = SplitFeatures.makeBooleanFragments(name="BooleanFragments") + BooleanFragments.Objects = [Wire, Air] + + # set view + doc.recompute() + if FreeCAD.GuiUp: + BooleanFragments.ViewObject.Transparency = 75 + BooleanFragments.ViewObject.Document.activeView().viewAxonometric() + BooleanFragments.ViewObject.Document.activeView().fitAll() + + # analysis + analysis = ObjectsFem.makeAnalysis(doc, "Analysis") + if FreeCAD.GuiUp: + import FemGui + FemGui.setActiveAnalysis(analysis) + + # solver + if solvertype == "elmer": + solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer") + eq_electrostatic = ObjectsFem.makeEquationMagnetodynamic(doc, solver_obj) + eq_electrostatic.AngularFrequency = "100 kHz" + eq_electrostatic.BiCGstablDegree = 4 + eq_electrostatic.IsHarmonic = True + eq_electrostatic.LinearIterativeMethod = "BiCGStabl" + eq_electrostatic.LinearPreconditioning = "None" + else: + FreeCAD.Console.PrintWarning( + "Not known or not supported solver type: {}. " + "No solver object was created.\n".format(solvertype) + ) + analysis.addObject(solver_obj) + + # material + + # air around the wire + material_obj = ObjectsFem.makeMaterialFluid(doc, "Air") + mat = material_obj.Material + mat["Name"] = "Air" + mat["Density"] = "1.204 kg/m^3" + mat["KinematicViscosity"] = "15.11 mm^2/s" + mat["VolumetricThermalExpansionCoefficient"] = "0.00 mm/m/K" + mat["ThermalConductivity"] = "0.02587 W/m/K" + mat["ThermalExpansionCoefficient"] = "0.00343/K" + mat["SpecificHeat"] = "1010.00 J/kg/K" + mat["ElectricalConductivity"] = "1e-12 S/m" + mat["RelativePermeability"] = "1.0" + mat["RelativePermittivity"] = "1.00059" + material_obj.Material = mat + material_obj.References = [(BooleanFragments, "Solid2")] + analysis.addObject(material_obj) + + # copper wire + material_obj = ObjectsFem.makeMaterialSolid(doc, "Copper") + mat = material_obj.Material + mat["Name"] = "Copper-Generic" + mat["Density"] = "8960 kg/m^3" + mat["PoissonRatio"] = "0.343" + mat["ShearModulus"] = "46 GPa" + mat["UltimateTensileStrength"] = "210 MPa" + mat["YoungsModulus"] = "119 GPa" + mat["ThermalConductivity"] = "398 W/m/K" + mat["ThermalExpansionCoefficient"] = "16.5 µm/m/K" + mat["SpecificHeat"] = "385 J/kg/K" + mat["ElectricalConductivity"] = "59590000 S/m" + mat["RelativePermeability"] = "0.999994" + material_obj.Material = mat + material_obj.References = [(BooleanFragments, "Solid1")] + analysis.addObject(material_obj) + + # axial field around the wire + AxialField = ObjectsFem.makeConstraintElectrostaticPotential(doc, "AxialField") + AxialField.References = [ + (BooleanFragments, "Face4"), + (BooleanFragments, "Face5"), + (BooleanFragments, "Face6")] + AxialField.PotentialEnabled = False + AxialField.AV_im_1_Disabled = False + AxialField.AV_im_2_Disabled = False + AxialField.AV_re_1_Disabled = False + AxialField.AV_re_2_Disabled = False + analysis.addObject(AxialField) + + # voltage on one end + Voltage = ObjectsFem.makeConstraintElectrostaticPotential(doc, "Voltage") + Voltage.References = [(BooleanFragments, "Face3")] + Voltage.Potential = "10.000 mV" + Voltage.AV_im_1_Disabled = False + Voltage.AV_im_2_Disabled = False + Voltage.AV_re_1_Disabled = False + Voltage.AV_re_2_Disabled = False + analysis.addObject(Voltage) + + # ground on other end + Ground = ObjectsFem.makeConstraintElectrostaticPotential(doc, "Ground") + Ground.References = [(BooleanFragments, "Face2")] + Ground.Potential = "0 V" + Ground.AV_im_1_Disabled = False + Ground.AV_im_2_Disabled = False + Ground.AV_re_1_Disabled = False + Ground.AV_re_2_Disabled = False + analysis.addObject(Ground) + + # magnetization + Magnetization = ObjectsFem.makeConstraintMagnetization(doc, "Magnetization") + Magnetization.References = [(BooleanFragments, "Solid1")] + Magnetization.Magnetization_re_1 = "7500.000 A/m" + Magnetization.Magnetization_re_2 = "7500.000 A/m" + Magnetization.Magnetization_re_3 = "7500.000 A/m" + Magnetization.Magnetization_re_2_Disabled = False + analysis.addObject(Magnetization) + + # mesh + femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0] + femmesh_obj.Part = BooleanFragments + femmesh_obj.ElementOrder = "1st" + femmesh_obj.CharacteristicLengthMax = "0.5 mm" + femmesh_obj.ViewObject.Visibility = False + + # mesh_region + mesh_region = ObjectsFem.makeMeshRegion(doc, femmesh_obj, name="MeshRegion") + mesh_region.CharacteristicLength = "0.15 mm" + mesh_region.References = [(BooleanFragments, "Solid1")] + mesh_region.ViewObject.Visibility = False + + # generate the mesh + from femmesh import gmshtools + gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis) + try: + error = gmsh_mesh.create_mesh() + except Exception: + error = sys.exc_info()[1] + FreeCAD.Console.PrintError( + "Unexpected error when creating mesh: {}\n" + .format(error) + ) + if error: + # try to create from existing rough mesh + from .meshes.mesh_capacitance_two_balls_tetra10 import create_nodes, create_elements + fem_mesh = Fem.FemMesh() + control = create_nodes(fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating nodes.\n") + control = create_elements(fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating elements.\n") + femmesh_obj.FemMesh = fem_mesh + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/manager.py b/src/Mod/Fem/femexamples/manager.py index b60a95be56..1b72f456ee 100644 --- a/src/Mod/Fem/femexamples/manager.py +++ b/src/Mod/Fem/femexamples/manager.py @@ -72,6 +72,7 @@ def run_all(): run_example("equation_electrostatics_electricforce_elmer_nongui6", run_solver=True) run_example("equation_flow_elmer_2D", run_solver=True) run_example("equation_flux_elmer", run_solver=True) + run_example("equation_magnetodynamics_elmer", run_solver=True) run_example("frequency_beamsimple", run_solver=True) run_example("material_multiple_bendingbeam_fiveboxes", run_solver=True) run_example("material_multiple_bendingbeam_fivefaces", run_solver=True) @@ -106,6 +107,7 @@ def setup_all(): run_example("equation_electrostatics_electricforce_elmer_nongui6") run_example("equation_flow_elmer_2D") run_example("equation_flux_elmer") + run_example("equation_magnetodynamics_elmer") run_example("frequency_beamsimple") run_example("material_multiple_bendingbeam_fiveboxes") run_example("material_multiple_bendingbeam_fivefaces")