Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: Assign initial mesh method #5556

Merged
merged 7 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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 @@

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

Check warning on line 856 in src/ansys/aedt/core/modules/mesh.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modules/mesh.py#L856

Added line #L856 was not covered by tests
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)

Check warning on line 953 in src/ansys/aedt/core/modules/mesh.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modules/mesh.py#L952-L953

Added lines #L952 - L953 were not covered by tests

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")

Samuelopez-ansys marked this conversation as resolved.
Show resolved Hide resolved
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
Loading