| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | __title__ = "FreeCAD FEM mesh netgen document object" |
| | __author__ = "Mario Passaglia" |
| | __url__ = "https://www.freecad.org" |
| |
|
| | |
| | |
| | |
| |
|
| | from FreeCAD import Base |
| | from . import base_fempythonobject |
| |
|
| | _PropHelper = base_fempythonobject._PropHelper |
| |
|
| |
|
| | class MeshNetgen(base_fempythonobject.BaseFemPythonObject): |
| | """ |
| | A Fem::FemMeshShapeBaseObject python type, add Netgen specific properties |
| | """ |
| |
|
| | Type = "Fem::FemMeshNetgen" |
| |
|
| | def __init__(self, obj): |
| | super().__init__(obj) |
| |
|
| | for prop in self._get_properties(): |
| | prop.add_to_object(obj) |
| |
|
| | def _get_properties(self): |
| | prop = [] |
| |
|
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyLinkList", |
| | name="MeshRegionList", |
| | group="Base", |
| | doc="Refinements of the mesh", |
| | value=[], |
| | ) |
| | ) |
| | |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyString", |
| | name="Optimize3d", |
| | group="Mesh Parameters", |
| | doc="3d optimization strategy.\n" |
| | + "m: move nodes, M: move nodes, cheap functional\n" |
| | + "s: swap faces, c: combine elements, d: divide elements,\n" |
| | + "D: divide and join opposite edges, remove element,\n" |
| | + "p: plot, no pause, P: plot, Pause,\n" |
| | + "h: Histogramm, no pause, H: Histogramm, pause", |
| | value="cmdDmustm", |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="OptimizationSteps3d", |
| | group="Mesh Parameters", |
| | doc="Number of 3d optimization steps", |
| | value={"value": 3, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyString", |
| | name="Optimize2d", |
| | group="Mesh Parameters", |
| | doc="2d optimization strategy.\n" |
| | + "s: swap opt 6 lines/node, S: swap optimal elements,\n" |
| | + "m: move nodes, p: plot, no pause\n" |
| | + "P: plot, pause, c: combine", |
| | value="smcmSmcmSmcm", |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="OptimizationSteps2d", |
| | group="Mesh Parameters", |
| | doc="Number of 2d optimization steps", |
| | value={"value": 3, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloat", |
| | name="OptimizationErrorPower", |
| | group="Mesh Parameters", |
| | doc="Power of error to approximate max error optimization", |
| | value=2.0, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="BlockFill", |
| | group="Mesh Parameters", |
| | doc="Do block filling", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyLength", |
| | name="FillDistance", |
| | group="Mesh Parameters", |
| | doc="Block filling up to distance", |
| | value=0.1, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="Safety", |
| | group="Mesh Parameters", |
| | doc="Radius of local environment (times h)", |
| | value={"value": 5.0, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="RelinnerSafety", |
| | group="Mesh Parameters", |
| | doc="Radius of active environment (times h)", |
| | value={"value": 3.0, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="LocalH", |
| | group="Mesh Parameters", |
| | doc="Use local h", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="UseLocalH", |
| | group="Mesh Parameters", |
| | doc="Use local H", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="GrowthRate", |
| | group="Mesh Parameters", |
| | doc="Grading for local h", |
| | value={"value": 0.3, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="Delaunay", |
| | group="Mesh Parameters", |
| | doc="Use Delaunay for 3d meshing", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="Delaunay2d", |
| | group="Mesh Parameters", |
| | doc="Use Delaunay for 2d meshing", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyLength", |
| | name="MaxSize", |
| | group="Mesh Parameters", |
| | doc="Maximal mesh size", |
| | value="1000 mm", |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyLength", |
| | name="MinSize", |
| | group="Mesh Parameters", |
| | doc="Minimal mesh size", |
| | value="0 mm", |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="CloseEdgeFactor", |
| | group="Mesh Parameters", |
| | doc="Factor to restrict meshing based on close edges", |
| | value={"value": 2.0, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="StartInSurface", |
| | group="Mesh Parameters", |
| | doc="Start surface meshing from everywhere in surface", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="CheckOverlap", |
| | group="Mesh Parameters", |
| | doc="Check overlapping surfaces", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="CheckOverlappingBoundary", |
| | group="Mesh Parameters", |
| | doc="Check overlapping surface mesh before volume meshing", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="CheckChartBoundary", |
| | group="Mesh Parameters", |
| | doc="Check chart boundary", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="CurvatureSafety", |
| | group="Mesh Parameters", |
| | doc="Safety factor for curvatures (elements per radius)", |
| | value={"value": 2.0, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="SegmentsPerEdge", |
| | group="Mesh Parameters", |
| | doc="Minimal number of segments per edge", |
| | value={"value": 2.0, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="ElementSizeWeight", |
| | group="Mesh Parameters", |
| | doc="Weight of element size respect to element shape", |
| | value={"value": 0.2, "min": 0, "step": 0.1}, |
| | ) |
| | ) |
| |
|
| | |
| | meshing_step = [ |
| | "AnalyzeGeometry", |
| | "MeshEdges", |
| | "MeshSurface", |
| | "OptimizeSurface", |
| | "MeshVolume", |
| | "OptimizeVolume", |
| | ] |
| |
|
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyEnumeration", |
| | name="StartStep", |
| | group="Mesh Parameters", |
| | doc="First step", |
| | value=meshing_step, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyEnumeration", |
| | name="EndStep", |
| | group="Mesh Parameters", |
| | doc="Last step", |
| | value=meshing_step, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="GiveUpTolerance2d", |
| | group="Mesh Parameters", |
| | doc="Give up quality class, 2d meshing", |
| | value={"value": 200, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="GiveUpTolerance", |
| | group="Mesh Parameters", |
| | doc="Give up quality class, 3d meshing", |
| | value={"value": 10, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="GiveUpToleranceOpenQuads", |
| | group="Mesh Parameters", |
| | doc="Give up quality class, for closing open quads, greater than 100 for free pyramids", |
| | value={"value": 15, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="MaxOuterSteps", |
| | group="Mesh Parameters", |
| | doc="Maximal outer steps", |
| | value={"value": 10, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="StarShapeClass", |
| | group="Mesh Parameters", |
| | doc="Class starting star-shape filling", |
| | value={"value": 5, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyInteger", |
| | name="BaseElementNp", |
| | group="Mesh Parameters", |
| | doc="If non-zero, baseelement must have BaseElementlNp points", |
| | value=0, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="Sloppy", |
| | group="Mesh Parameters", |
| | doc="Quality tolerances are handled less careful", |
| | value={"value": 10, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatConstraint", |
| | name="BadElementLimit", |
| | group="Mesh Parameters", |
| | doc="Limit for max element angle (150-180)", |
| | value={"value": 175, "min": 0}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="CheckImpossible", |
| | group="Mesh Parameters", |
| | doc="", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyInteger", |
| | name="Only3dDomainNr", |
| | group="Mesh Parameters", |
| | doc="", |
| | value=0, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="SecondOrder", |
| | group="Mesh Parameters", |
| | doc="Second order element meshing", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="SecondOrderLinear", |
| | group="Mesh Parameters", |
| | doc="Second order nodes are created by linear interpolation", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyIntegerConstraint", |
| | name="ElementOrder", |
| | group="Mesh Parameters", |
| | doc="High order element curvature", |
| | value={"value": 1, "min": 1}, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="QuadDominated", |
| | group="Mesh Parameters", |
| | doc="Quad-dominated surface meshing", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="TryHexes", |
| | group="Mesh Parameters", |
| | doc="Try hexahedral elements", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="InvertTets", |
| | group="Mesh Parameters", |
| | doc="", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="InvertTrigs", |
| | group="Mesh Parameters", |
| | doc="", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyEnumeration", |
| | name="ZRefine", |
| | group="Mesh Parameters", |
| | doc="Z-refinement for extruded shapes", |
| | value=["No", "Regular", "Custom"], |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyVector", |
| | name="ZRefineDirection", |
| | group="Mesh Parameters", |
| | doc="Z-refinement direction", |
| | value=Base.Vector(0, 0, 1), |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyFloatList", |
| | name="ZRefineSize", |
| | group="Mesh Parameters", |
| | doc="Z-refinement size given as a fraction of the shape size.\n" |
| | + "For a regular partition only one value is needed", |
| | value=[ |
| | 0.1, |
| | ], |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="ParallelMeshing", |
| | group="Mesh Parameters", |
| | doc="Use parallel meshing", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="HealShape", |
| | group="Mesh Parameters", |
| | doc="Heal shape before meshing", |
| | value=False, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyBool", |
| | name="Glue", |
| | group="Mesh Parameters", |
| | doc="Glue shapes to get a conformal mesh", |
| | value=True, |
| | ) |
| | ) |
| | prop.append( |
| | _PropHelper( |
| | type="App::PropertyEnumeration", |
| | name="Fineness", |
| | group="Mesh Parameters", |
| | doc="Mesh granularity.\n" |
| | + "If differs from UserDefined, uses specific values\n" |
| | + "for CurvatureSafety, SegmentsPerEdge, GrowthRate,\n" |
| | + "CloseEdgeFactor and OptimizationSteps3d", |
| | value=["VeryCoarse", "Coarse", "Moderate", "Fine", "VeryFine", "UserDefined"], |
| | ) |
| | ) |
| |
|
| | return prop |
| |
|
| | def onChanged(self, obj, prop): |
| | if prop == "Fineness": |
| | if obj.Fineness != "UserDefined": |
| | p = self.get_predef_fineness_params(obj.Fineness) |
| | obj.CurvatureSafety = p["curvaturesafety"] |
| | obj.SegmentsPerEdge = p["segmentsperedge"] |
| | obj.GrowthRate = p["grading"] |
| | obj.CloseEdgeFactor = p["closeedgefac"] |
| | obj.OptimizationSteps3d = p["optsteps3d"] |
| |
|
| | obj.setPropertyStatus("CurvatureSafety", "ReadOnly") |
| | obj.setPropertyStatus("SegmentsPerEdge", "ReadOnly") |
| | obj.setPropertyStatus("GrowthRate", "ReadOnly") |
| | obj.setPropertyStatus("CloseEdgeFactor", "ReadOnly") |
| | obj.setPropertyStatus("OptimizationSteps3d", "ReadOnly") |
| | else: |
| | obj.setPropertyStatus("CurvatureSafety", "-ReadOnly") |
| | obj.setPropertyStatus("SegmentsPerEdge", "-ReadOnly") |
| | obj.setPropertyStatus("GrowthRate", "-ReadOnly") |
| | obj.setPropertyStatus("CloseEdgeFactor", "-ReadOnly") |
| | obj.setPropertyStatus("OptimizationSteps3d", "-ReadOnly") |
| |
|
| | def onDocumentRestored(self, obj): |
| | |
| | for prop in self._get_properties(): |
| | try: |
| | obj.getPropertyByName(prop.name) |
| | except Base.PropertyError: |
| | prop.add_to_object(obj) |
| |
|
| | |
| | if prop.name == "StartStep" or prop.name == "EndStep": |
| | prop.handle_change_type( |
| | obj, "App::PropertyInteger", lambda x: 0 if x <= 1 else 5 if x >= 6 else x - 1 |
| | ) |
| | |
| | setattr(obj, prop.name, prop.value) |
| |
|
| | def get_predef_fineness_params(self, fineness): |
| | |
| | params = {} |
| | if fineness == "VeryCoarse": |
| | params["curvaturesafety"] = 1 |
| | params["segmentsperedge"] = 0.3 |
| | params["grading"] = 0.7 |
| | params["closeedgefac"] = 0.5 |
| | params["optsteps3d"] = 5 |
| | elif fineness == "Coarse": |
| | params["curvaturesafety"] = 1.5 |
| | params["segmentsperedge"] = 0.5 |
| | params["grading"] = 0.5 |
| | params["closeedgefac"] = 1 |
| | params["optsteps3d"] = 5 |
| | elif fineness == "Moderate": |
| | params["curvaturesafety"] = 2 |
| | params["segmentsperedge"] = 1 |
| | params["grading"] = 0.3 |
| | params["closeedgefac"] = 2 |
| | params["optsteps3d"] = 5 |
| | elif fineness == "Fine": |
| | params["curvaturesafety"] = 3 |
| | params["segmentsperedge"] = 2 |
| | params["grading"] = 0.2 |
| | params["closeedgefac"] = 3.5 |
| | params["optsteps3d"] = 5 |
| | elif fineness == "VeryFine": |
| | params["curvaturesafety"] = 5 |
| | params["segmentsperedge"] = 3 |
| | params["grading"] = 0.1 |
| | params["closeedgefac"] = 5 |
| | params["optsteps3d"] = 5 |
| | elif fineness == "UserDefined": |
| | params["curvaturesafety"] = 2 |
| | params["segmentsperedge"] = 2 |
| | params["grading"] = 0.3 |
| | params["closeedgefac"] = 2 |
| | params["optsteps3d"] = 3 |
| |
|
| | return params |
| |
|