Skip to content

Commit 8df5098

Browse files
committed
Merge branch 'master' of https://github.com/ansys/pydpf-core
2 parents 6ce3f22 + f90f640 commit 8df5098

File tree

15 files changed

+150
-38
lines changed

15 files changed

+150
-38
lines changed

doc/source/_static/dpf_operators.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6604,7 +6604,7 @@ <h2 class="h2-main">Configurating operators</h2>
66046604
</div></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="9" ellipsis = "false"></pin-number-optional></td><td><pin-name name="requested_location"></pin-name></td><td><req-type typeName="(string)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="14" ellipsis = "false"></pin-number-optional></td><td><pin-name name="read_cyclic"></pin-name></td><td><req-type typeName="(enum dataProcessing::ECyclicReading | int32)"></req-type></td><td><div class = "pin-des-text"><p>if 0 cyclic symmetry is ignored, if 1 cyclic sector is read, if 2 cyclic expansion is done, if 3 cyclic expansion is done and stages are merged (default is 1)</p>
66056605
</div></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="22" ellipsis = "false"></pin-number-optional></td><td><pin-name name="read_beams"></pin-name></td><td><req-type typeName="(bool)"></req-type></td><td><div class = "pin-des-text"><p>elemental nodal beam results are read if this pin is set to true (default is false)</p>
66066606
</div></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="fields_container"></pin-name></td><td><req-type typeName="(fields_container)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><config-spec name="num_threads" default="0" doc="Number of threads to use to run in parallel" types="int32" ></config-spec><config-spec name="run_in_parallel" default="true" doc="Loops are allowed to run in parallel if the value of this config is set to true." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="elastic_strain_principal_2" license="none" cat="result" plugin="core" cpp-name="EPEL2"></scripting-part></div><div class="operator" id="scoping normals" scripting_name="normals"plugin="core"cat="geo"><h1 class="op-des-h1">geo: scoping normals</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>compute the normals at the given nodes or element scoping based on the given mesh (first version, the element normal is only handled on the shell elements)</p>
6607-
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number-optional n="0" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh"></pin-name></td><td><req-type typeName="(abstract_meshed_region)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="1" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh_scoping"></pin-name></td><td><req-type typeName="(scoping)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="3" ellipsis = "false"></pin-number-optional></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="normals" license="any_dpf_supported_increments" cat="geo" plugin="core" cpp-name="normals_provider"></scripting-part></div><div class="operator" id="merge scopings" scripting_name="merge_scopings"plugin="core"cat="utility"><h1 class="op-des-h1">utility: merge scopings</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Assembles a set of scopings into a unique one.</p>
6607+
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number-optional n="0" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh"></pin-name></td><td><req-type typeName="(abstract_meshed_region)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="1" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh_scoping"></pin-name></td><td><req-type typeName="(scoping)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="3" ellipsis = "false"></pin-number-optional></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="normals" license="none" cat="geo" plugin="core" cpp-name="normals_provider"></scripting-part></div><div class="operator" id="merge scopings" scripting_name="merge_scopings"plugin="core"cat="utility"><h1 class="op-des-h1">utility: merge scopings</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Assembles a set of scopings into a unique one.</p>
66086608
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "true"></pin-number></td><td><pin-name name="scopings"></pin-name></td><td><req-type typeName="(scoping | scopings_container | vector<shared_ptr<scoping>>)"></req-type></td><td><div class = "pin-des-text"><p>Either a scopings container, a vector of scopings to merge, or scopings from pin 0 to ...</p>
66096609
</div></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="merged_scoping"></pin-name></td><td><req-type typeName="(scoping)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="merge_scopings" license="none" cat="utility" plugin="core" cpp-name="merge::scoping"></scripting-part></div><div class="operator" id="elastic strain principal 3" scripting_name="elastic_strain_principal_3"plugin="core"cat="result"><h1 class="op-des-h1">result: elastic strain principal 3</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Read/compute element nodal component elastic strains 3rd principal component by calling the readers defined by the datasources and computing its eigen values. The off-diagonal strains are first converted from Voigt notation to the standard strain values.</p>
66106610
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number-optional n="0" ellipsis = "false"></pin-number-optional></td><td><pin-name name="time_scoping"></pin-name></td><td><req-type typeName="(scoping | int32 | vector<int32> | double | field | vector<double>)"></req-type></td><td><div class = "pin-des-text"><p>time/freq values (use doubles or field), time/freq set ids (use ints or scoping) or time/freq step ids (use scoping with TimeFreq_steps location) required in output. To specify time/freq values at specific load steps, put a Field (and not a list) in input with a scoping located on &quot;TimeFreq_steps&quot;. Linear time freq intrapolation is performed if the values are not in the result files and the data at the max time or freq is taken when time/freqs are higher than available time/freqs in result files. To get all data for all time/freq sets, connect an int with value -1.</p>
@@ -8950,7 +8950,7 @@ <h2 class="h2-main">Configurating operators</h2>
89508950
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="mesh"></pin-name></td><td><req-type typeName="(abstract_meshed_region)"></req-type></td><td><div class = "pin-des-text"><p>Skin, face, or shell mesh region.</p>
89518951
</div></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="1" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh_scoping"></pin-name></td><td><req-type typeName="(scoping)"></req-type></td><td><div class = "pin-des-text"><p>Elemental, ElementalNodal, or Nodal scoping. Location derived from this.</p>
89528952
</div></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="9" ellipsis = "false"></pin-number-optional></td><td><pin-name name="requested_location"></pin-name></td><td><req-type typeName="(string)"></req-type></td><td><div class = "pin-des-text"><p>If no scoping, specifies location. If scoping is Elemental or ElementalNodal this overrides scoping. Default is Elemental.</p>
8953-
</div></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="normals_provider_nl" license="any_dpf_supported_increments" cat="geo" plugin="core" cpp-name="normals_provider_nl"></scripting-part></div><div class="operator" id="elements volumes over time" scripting_name="elements_volumes_over_time"plugin="core"cat="geo"><h1 class="op-des-h1">geo: elements volumes over time</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Calculates for a mesh, the volume of each element over time for each specified time step.</p>
8953+
</div></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="field"></pin-name></td><td><req-type typeName="(field)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="normals_provider_nl" license="none" cat="geo" plugin="core" cpp-name="normals_provider_nl"></scripting-part></div><div class="operator" id="elements volumes over time" scripting_name="elements_volumes_over_time"plugin="core"cat="geo"><h1 class="op-des-h1">geo: elements volumes over time</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Calculates for a mesh, the volume of each element over time for each specified time step.</p>
89548954
</div></figure><h2 class="op-des-h2">Inputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number-optional n="1" ellipsis = "false"></pin-number-optional></td><td><pin-name name="scoping"></pin-name></td><td><req-type typeName="(scoping)"></req-type></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="2" ellipsis = "false"></pin-number-optional></td><td><pin-name name="displacement"></pin-name></td><td><req-type typeName="(fields_container)"></req-type></td><td><div class = "pin-des-text"><p>Displacement field's container. Must contain the mesh if mesh not specified in input.</p>
89558955
</div></td></tr></tbody></table><table class="pin-box"><tbody><tr><td><pin-number-optional n="7" ellipsis = "false"></pin-number-optional></td><td><pin-name name="mesh"></pin-name></td><td><req-type typeName="(abstract_meshed_region)"></req-type></td><td><div class = "pin-des-text"><p>Mesh must be defined if the displacement field's container does not contain it, or if there is no displacement.</p>
89568956
</div></td></tr></tbody></table></div><h2 class="op-des-h2">Outputs</h2><div><table class="pin-box"><tbody><tr><td><pin-number n="0" ellipsis = "false"></pin-number></td><td><pin-name name="fields_container"></pin-name></td><td><req-type typeName="(fields_container)"></req-type></td></tr></tbody></table></div><h2 class="op-des-h2">Configurations</h2><config-spec name="mutex" default="false" doc="If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads." types="bool" ></config-spec><h2 class="op-des-h2">Scripting</h2><scripting-part scripting_name="elements_volumes_over_time" license="any_dpf_supported_increments" cat="geo" plugin="core" cpp-name="volumes_provider"></scripting-part></div><div class="operator" id="window bartlett" scripting_name="window_bartlett"plugin="core"cat="math"><h1 class="op-des-h1">math: window bartlett</h1><figure class="figure-op-des"> <figcaption > Description </figcaption><div class = "figure-op-des-text"><p>Apply bartlett windowing on a given FieldsContainer having time label or a Field located on time. Assume that time sampling is evenly spaced (use time_freq_interpolation before otherwise).</p>

examples/02-modal_analyses/01-plot_and_animate_modes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@
7272
# To suppress window pop-up, set the `off_screen` argument to True.
7373
# ~~~~~~~~~~~~~~~~~~~~
7474

75-
animation.animate_mode(disp, mode_number=1, save_as="tmp.gif", off_screen=True)
75+
animation.animate_mode(
76+
disp, mode_number=1, save_as="tmp.gif", off_screen=True, deform_scale_factor=10.0
77+
)

src/ansys/dpf/core/animation.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,14 @@ def animate_mode(
9595
)
9696

9797
# Get fields
98+
available_mode_numbers = fields_container.get_available_ids_for_label("time")
99+
100+
if not mode_number in available_mode_numbers:
101+
raise ValueError(f"The mode {mode_number} data is not available in field container.")
98102
fields_mode = fields_container.get_fields({"time": mode_number})
103+
mode_frequencies_field = fields_container.time_freq_support.time_frequencies
104+
mode_frequencies = mode_frequencies_field.data
105+
mode_frequency = mode_frequencies[available_mode_numbers.index(mode_number)]
99106

100107
# Merge fields if needed
101108
if len(fields_mode) > 1:
@@ -108,6 +115,7 @@ def animate_mode(
108115

109116
max_data = float(np.max(field_mode.data))
110117
loop_over = dpf.fields_factory.field_from_array(scale_factor_per_frame)
118+
loop_over.unit = mode_frequencies_field.unit
111119

112120
# Create workflow
113121
wf = dpf.Workflow()
@@ -120,6 +128,7 @@ def animate_mode(
120128

121129
wf.set_input_name("weights", scaling_op.inputs.weights)
122130
wf.set_output_name("field", scaling_op.outputs.field)
131+
wf.set_output_name("deform_by", scaling_op.outputs.field)
123132

124133
anim = Animator(workflow=wf, **kwargs)
125134

@@ -129,6 +138,8 @@ def animate_mode(
129138
output_name="field",
130139
save_as=save_as,
131140
mode_number=mode_number,
141+
mode_frequency=mode_frequency,
132142
clim=[0, max_data],
143+
scale_factor=deform_scale_factor,
133144
**kwargs,
134145
)

src/ansys/dpf/core/animator.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def animate_workflow(
5959
input_name="loop_over",
6060
save_as="",
6161
mode_number=None,
62+
mode_frequency=None,
6263
scale_factor=1.0,
6364
shell_layer=core.shell_layers.top,
6465
**kwargs,
@@ -70,7 +71,7 @@ def animate_workflow(
7071
scale_factor = [False] * len(indices)
7172
type_scale = type(scale_factor)
7273
if type_scale in [int, float]:
73-
scale_factor = [scale_factor] * len(indices)
74+
scale_factor = [float(scale_factor)] * len(indices)
7475
elif type_scale == list:
7576
pass
7677
# elif type_scale in [core.field.Field, core.fields_container.FieldsContainer]:
@@ -121,6 +122,7 @@ def render_frame(frame):
121122
self.add_field(
122123
field,
123124
deform_by=deform,
125+
scale_factor=scale_factor[frame],
124126
scale_factor_legend=scale_factor[frame],
125127
shell_layer=shell_layer,
126128
**kwargs,
@@ -132,9 +134,9 @@ def render_frame(frame):
132134
str_template.format(indices[frame], unit, freq_fmt), **kwargs_in
133135
)
134136
else:
135-
str_template = "frq={0:{2}} {1}"
137+
str_template = "mode={3}\nfrq={0:{2}} {1}"
136138
self._plotter.add_text(
137-
str_template.format(mode_number, unit, freq_fmt), **kwargs_in
139+
str_template.format(mode_frequency, unit, freq_fmt, mode_number), **kwargs_in
138140
)
139141

140142
if cpos:

src/ansys/dpf/core/data_sources.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from __future__ import annotations
2626

2727
import os
28-
from pathlib import Path
28+
from pathlib import Path, PurePosixPath, PureWindowsPath
2929
import traceback
3030
from typing import TYPE_CHECKING, Union
3131
import warnings
@@ -159,7 +159,9 @@ def set_result_file_path(
159159
['...tmp...file.rst']
160160
161161
"""
162-
filepath = Path(filepath)
162+
filepath = (
163+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
164+
)
163165
extension = filepath.suffix
164166
# Handle .res files from CFX
165167
if key == "" and extension == ".res":
@@ -290,7 +292,7 @@ def set_domain_result_file_path(
290292
>>> my_data_sources.set_domain_result_file_path(path='/tmp/file1.rst', key='rst', domain_id=1)
291293
292294
"""
293-
path = Path(path)
295+
path = PurePosixPath(path) if self._server.os == "posix" else PureWindowsPath(path)
294296
if key:
295297
self._api.data_sources_set_domain_result_file_path_with_key_utf8(
296298
self, str(path), key, domain_id
@@ -341,7 +343,9 @@ def add_file_path(
341343
# The filename needs to be a fully qualified file name
342344
# if not os.path.dirname(filepath)
343345

344-
filepath = Path(filepath)
346+
filepath = (
347+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
348+
)
345349
if not filepath.parent.name:
346350
# append local path
347351
filepath = Path.cwd() / filepath.name
@@ -391,7 +395,9 @@ def add_domain_file_path(
391395
392396
"""
393397
# The filename needs to be a fully qualified file name
394-
filepath = Path(filepath)
398+
filepath = (
399+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
400+
)
395401
if not filepath.parent.name:
396402
# append local path
397403
filepath = Path.cwd() / filepath.name
@@ -424,7 +430,9 @@ def add_file_path_for_specified_result(
424430
The default is ``""``, in which case the key is found directly.
425431
"""
426432
# The filename needs to be a fully qualified file name
427-
filepath = Path(filepath)
433+
filepath = (
434+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
435+
)
428436
if not filepath.parent.name:
429437
# append local path
430438
filepath = Path.cwd() / filepath.name

0 commit comments

Comments
 (0)