| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| __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 |
|
|