Skip to content

Commit

Permalink
FEAT: Assign initial mesh method (#5556)
Browse files Browse the repository at this point in the history
Co-authored-by: Sébastien Morais <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 12, 2024
1 parent 7ff7050 commit 67d3abc
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 37 deletions.
183 changes: 151 additions & 32 deletions src/ansys/aedt/core/modules/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,43 +786,51 @@ def assign_model_resolution(self, assignment, defeature_length=None, name=None):
self.meshoperations.append(mop)
return mop

@pyaedt_function_handler()
@pyaedt_function_handler(
usedynamicsurface="dynamic_surface",
useflexmesh="flex_mesh",
applycurvilinear="curvilinear",
usefallback="fallback",
usephi="phi",
automodelresolution="auto_model_resolution",
modelresolutionlength="model_resolution_length",
)
def assign_initial_mesh_from_slider(
self,
level=5,
method="Auto",
usedynamicsurface=True,
useflexmesh=False,
applycurvilinear=False,
usefallback=True,
usephi=True,
automodelresolution=True,
modelresolutionlength="0.0001mm",
dynamic_surface=True,
flex_mesh=False,
curvilinear=False,
fallback=True,
phi=True,
auto_model_resolution=True,
model_resolution_length="0.0001mm",
):
"""Assign a surface mesh level to an object.
Parameters
----------
level : int, optional
Level of the surface mesh. Options are ``1`` through ``10``. The default is ``5.``
Level of the surface mesh. Options are ``1`` through ``10``. The default is ``5``.
method : str, optional
Meshing method. Options are ``"Auto"``, ``"AnsoftTAU"``, and ``"AnsoftClassic"``
The default is ``"Auto"``.
usedynamicsurface : bool, optional
Whether to use a dynamic surface. The default is ``True``.
useflexmesh : bool, optional
Whether to use a flexible mesh. The default is ``False``.
applycurvilinear : bool, optional
dynamic_surface : bool, optional
Whether to use dynamic surface resolution. The default is ``True``.
flex_mesh : bool, optional
Whether to use flexible mesh for TAU volume mesh. The default is ``False``.
curvilinear : bool, optional
Whether to apply curvilinear elements. The default is ``False``.
usefallback : bool, optional
fallback : bool, optional
Whether to retain as a fallback. The default is ``True``.
usephi : bool, optional
phi : bool, optional
Whether to use the Phi mesher for layered geometry.
The default is ``True``.
automodelresolution : bool, optional
auto_model_resolution : bool, optional
Whether to automatically calculate the resolution length
based on each object's effective thickness. The default is ``True``.
modelresolutionlength : float, optional
model_resolution_length : float, optional
Resolution thickness with units if ``automodelresolution=False``.
The default ``"0.0001mm"``.
Expand All @@ -836,46 +844,157 @@ def assign_initial_mesh_from_slider(
>>> oModule.InitialMeshSettings
"""
if self._app.design_type == "2D Extractor" or self._app.design_type == "Maxwell 2D":
if self._app.design_type in ["2D Extractor", "Maxwell 2D"]:
mesh_methods = ["Auto", "AnsoftClassic"]
else:
mesh_methods = ["Auto", "AnsoftTAU", "AnsoftClassic"]
if method not in mesh_methods:
raise RuntimeError(f"Invalid mesh method {method}") # pragma: no cover
raise ValueError(f"Invalid mesh method {method}")

modelres = ["NAME:GlobalModelRes", "UseAutoLength:=", automodelresolution]
if not automodelresolution:
modelres.append("DefeatureLength:=")
modelres.append(modelresolutionlength)
modelres = ["NAME:GlobalModelRes", "UseAutoLength:=", auto_model_resolution]
if not auto_model_resolution:
modelres += ["DefeatureLength:=", model_resolution_length]
surface_appr = [
"NAME:GlobalSurfApproximation",
"CurvedSurfaceApproxChoice:=",
"UseSlider",
"SliderMeshSettings:=",
level,
]
if self._app.design_type == "2D Extractor" or self._app.design_type == "Maxwell 2D":

if self._app.design_type in ["2D Extractor", "Maxwell 2D"]:
args = ["NAME:MeshSettings", surface_appr, modelres, "MeshMethod:=", method]
else:
args = [
"NAME:MeshSettings",
surface_appr,
["NAME:GlobalCurvilinear", "Apply:=", curvilinear],
modelres,
"MeshMethod:=",
method,
"UseLegacyFaceterForTauVolumeMesh:=",
False,
"DynamicSurfaceResolution:=",
dynamic_surface,
"UseFlexMeshingForTAUvolumeMesh:=",
flex_mesh,
]
if self._app.design_type == "HFSS":
args += ["UseAlternativeMeshMethodsAsFallBack:=", fallback, "AllowPhiForLayeredGeometry:=", phi]
self.omeshmodule.InitialMeshSettings(args)
return True

@pyaedt_function_handler()
def assign_initial_mesh(
self,
method="Auto",
surface_deviation=None,
normal_deviation=None,
aspect_ratio=None,
flex_mesh=False,
curvilinear=False,
fallback=True,
phi=True,
auto_model_resolution=True,
model_resolution_length="0.0001mm",
):
"""Assign a surface mesh level to an object.
Parameters
----------
method : str, optional
Meshing method. Options are ``"Auto"``, ``"AnsoftTAU"``, and ``"AnsoftClassic"``
The default is ``"Auto"``.
surface_deviation : float or str, optional
Surface deviation.
The default is ``None``, in which case the default value is assigned.
normal_deviation : float or str, optional
Normal deviation.
The default is ``None``, in which case the default value is assigned.
aspect_ratio : float or str, optional
Aspect ratio.
The default is ``None``, in which case the default value is assigned.
flex_mesh : bool, optional
Whether to use flexible mesh for TAU volume mesh. The default is ``False``.
curvilinear : bool, optional
Whether to apply curvilinear elements. The default is ``False``.
fallback : bool, optional
Whether to retain as a fallback. The default is ``True``.
phi : bool, optional
Whether to use the Phi mesher for layered geometry.
The default is ``True``.
auto_model_resolution : bool, optional
Whether to automatically calculate the resolution length
based on each object's effective thickness. The default is ``True``.
model_resolution_length : float or str, optional
Resolution thickness with units if ``automodelresolution=False``.
The default ``"0.0001mm"``.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
References
----------
>>> oModule.InitialMeshSettings
"""
if self._app.design_type in ["2D Extractor", "Maxwell 2D"]:
mesh_methods = ["Auto", "AnsoftClassic"]
else:
mesh_methods = ["Auto", "AnsoftTAU", "AnsoftClassic"]
if method not in mesh_methods:
raise ValueError(f"Invalid mesh method {method}")

modelres = ["NAME:GlobalModelRes", "UseAutoLength:=", auto_model_resolution]
if not auto_model_resolution:
modelres.append("DefeatureLength:=")
modelres.append(model_resolution_length)

surface_appr = [
"NAME:GlobalSurfApproximation",
"CurvedSurfaceApproxChoice:=",
"ManualSettings",
"SurfDevChoice:=",
]

if not surface_deviation:
surface_appr.append(0)
else:
surface_appr += [2, "SurfDev:=", surface_deviation]

surface_appr.append("NormalDevChoice:=")
if not normal_deviation:
surface_appr.append(1)
else:
surface_appr += [2, "NormalDev:=", normal_deviation]

surface_appr.append("AspectRatioChoice:=")
if not aspect_ratio:
surface_appr.append(1)
else:
surface_appr += [2, "AspectRatio:=", aspect_ratio]

if self._app.design_type in ["2D Extractor", "Maxwell 2D"]:
args = ["NAME:MeshSettings", surface_appr, modelres, "MeshMethod:=", method]
else:
args = [
"NAME:MeshSettings",
surface_appr,
["NAME:GlobalCurvilinear", "Apply:=", applycurvilinear],
["NAME:GlobalCurvilinear", "Apply:=", curvilinear],
modelres,
"MeshMethod:=",
method,
"UseLegacyFaceterForTauVolumeMesh:=",
False,
"DynamicSurfaceResolution:=",
usedynamicsurface,
False,
"UseFlexMeshingForTAUvolumeMesh:=",
useflexmesh,
flex_mesh,
]
if self._app.design_type == "HFSS":
args.append("UseAlternativeMeshMethodsAsFallBack:=")
args.append(usefallback)
args.append("AllowPhiForLayeredGeometry:=")
args.append(usephi)
args += ["UseAlternativeMeshMethodsAsFallBack:=", fallback, "AllowPhiForLayeredGeometry:=", phi]
self.omeshmodule.InitialMeshSettings(args)
return True

Expand Down
6 changes: 5 additions & 1 deletion tests/system/general/test_20_HFSS.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,9 +902,13 @@ def test_24_create_curvilinear(self):
mesh.delete()
assert len(self.aedtapp.mesh.meshoperations) == 2

def test_30_assign_initial_mesh(self):
def test_30a_assign_initial_mesh(self):
assert self.aedtapp.mesh.assign_initial_mesh_from_slider(6)

def test_03b_assign_initial_mesh(self):
assert self.aedtapp.mesh.assign_initial_mesh()
assert self.aedtapp.mesh.assign_initial_mesh(normal_deviation="25deg", surface_deviation=0.2, aspect_ratio=20)

def test_30a_add_mesh_link(self):
design_name = self.aedtapp.design_name
nominal_adaptive = self.aedtapp.nominal_adaptive
Expand Down
13 changes: 12 additions & 1 deletion tests/system/general/test_27_Maxwell2D.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,20 @@ def init(self, aedtapp, m2d_ctrl_prg, m2d_field_export, m2d_circuit, local_scrat
self.m2d_circuit = m2d_circuit
self.local_scratch = local_scratch

def test_03_assign_initial_mesh_from_slider(self):
def test_03a_assign_initial_mesh_from_slider(self):
assert self.aedtapp.mesh.assign_initial_mesh_from_slider(4)

def test_03a_assign_initial_mesh_from_slider_failure_due_to_wrong_method(self):
with pytest.raises(ValueError):
self.aedtapp.mesh.assign_initial_mesh_from_slider(method="dummy")

def test_03b_assign_initial_mesh(self):
assert self.aedtapp.mesh.assign_initial_mesh(surface_deviation="2mm")

def test_03b_assign_initial_mesh_failure_due_to_wrong_method(self):
with pytest.raises(ValueError):
self.aedtapp.mesh.assign_initial_mesh(method="dummy")

def test_04_create_winding(self):
bounds = self.aedtapp.assign_winding(assignment=["Coil"], current=20e-3)
assert bounds
Expand Down
9 changes: 6 additions & 3 deletions tests/system/general/test_28_Maxwell3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,18 @@ def test_24_create_curvilinear(self):
def test_24_create_edge_cut(self):
assert self.aedtapp.mesh.assign_edge_cut(["Coil"])

def test_24_density_control(self):
def test_24a_density_control(self):
assert self.aedtapp.mesh.assign_density_control(["Coil"], maximum_element_length="2mm", layers_number="3")

def test_24_density_control(self):
def test_24b_density_control(self):
assert self.aedtapp.mesh.assign_rotational_layer(["Coil"])

def test_25_assign_initial_mesh(self):
def test_25a_assign_initial_mesh(self):
assert self.aedtapp.mesh.assign_initial_mesh_from_slider(4)

def test_25b_assign_initial_mesh(self):
assert self.aedtapp.mesh.assign_initial_mesh(surface_deviation="2mm")

@pytest.mark.skipif(is_linux, reason="Crashing on Linux")
def test_26_create_udp(self):
my_udpPairs = []
Expand Down

0 comments on commit 67d3abc

Please sign in to comment.