Skip to content
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
29 changes: 27 additions & 2 deletions ansys/dpf/core/examples/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os
import urllib.request


EXAMPLE_REPO = "https://github.com/pyansys/example-data/raw/master/result_files/"


Expand All @@ -22,7 +21,8 @@ def _retrieve_file(url, filename, directory):
"""Download a file from a url"""
from ansys.dpf.core import LOCAL_DOWNLOADED_EXAMPLES_PATH, path_utilities
# First check if file has already been downloaded
local_path = os.path.join(LOCAL_DOWNLOADED_EXAMPLES_PATH, directory, os.path.basename(filename))
local_path = os.path.join(LOCAL_DOWNLOADED_EXAMPLES_PATH, directory,
os.path.basename(filename))
local_path_no_zip = local_path.replace(".zip", "")
if os.path.isfile(local_path_no_zip) or os.path.isdir(local_path_no_zip):
return path_utilities.to_server_os(local_path_no_zip.replace(
Expand Down Expand Up @@ -380,3 +380,28 @@ def download_extrapolation_2d_result() -> dict:
}

return dict


def download_hemisphere() -> str:
"""Download an example result file from a static analysis and
return the download path.

Examples files are downloaded to a persistent cache to avoid
re-downloading the same file twice.

Returns
-------
str
Path to the example file.

Examples
--------
Download an example result file and return the path of the file

>>> from ansys.dpf.core import examples
>>> path = examples.download_hemisphere()
>>> path
'C:/Users/user/AppData/local/temp/hemisphere.rst'

"""
return _download_file("hemisphere", "hemisphere.rst")
145 changes: 145 additions & 0 deletions examples/03-advanced/06-stress_gradient_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""
.. _stress_gradient_path:

Stress gradient normal to a defined node.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example shows how to plot a stress gradient normal to a selected node.
As the example is based on creating a path along the normal, the selected node
must be on the surface of the geometry.
A path is created of a defined length.

"""

###############################################################################
# First, import the DPF-Core module as ``dpf`` and import the
# included examples file and ``DpfPlotter``
#
import matplotlib.pyplot as plt
from ansys.dpf import core as dpf
from ansys.dpf.core import operators as ops
from ansys.dpf.core.plotter import DpfPlotter
from ansys.dpf.core import examples

###############################################################################
# Next, open an example and print out the ``model`` object. The
# :class:`Model <ansys.dpf.core.model.Model> class helps to organize access
# methods for the result by keeping track of the operators and data sources
# used by the result file.
#
# Printing the model displays:
#
# - Analysis type
# - Available results
# - Size of the mesh
# - Number of results
# - Unit
#
path = examples.download_hemisphere()
model = dpf.Model(path)
print(model)
###############################################################################
# Define the `node_id` normal to which a stress gradient should be plotted.
#
node_id = 1928
###############################################################################
# The following command prints the mesh unit
#
unit = model.metadata.meshed_region.unit
print("Unit: %s" % unit)
###############################################################################
# `depth` defines the path length / depth to which the path will penetrate.
# While defining `depth` make sure you use the correct mesh unit.
# `delta` defines distance between consecutive points on the path.
depth = 10 # in mm
delta = 0.1 # in mm
###############################################################################
# Get the meshed region
#
mesh = model.metadata.meshed_region
###############################################################################
# Get Equivalent stress fields container.
#
stress_fc = model.results.stress().eqv().outputs.fields_container()
###############################################################################
# Define Nodal scoping.
# Make sure to define ``"Nodal"`` as the requested location, important for the
# `normals` operator.
#
nodal_scoping = dpf.Scoping(location=dpf.locations.nodal)
nodal_scoping.ids = [node_id]
###############################################################################
# Get Skin Mesh because `normals` operator requires Shells as input.
#
skin_mesh = ops.mesh.skin(mesh=mesh)
skin_meshed_region = skin_mesh.outputs.mesh.get_data()
###############################################################################
# Get normal at a node using `normals` operator.
#
normal = ops.geo.normals()
normal.inputs.mesh.connect(skin_meshed_region)
normal.inputs.mesh_scoping.connect(nodal_scoping)
normal_vec_out_field = normal.outputs.field.get_data()
###############################################################################
# Normal vector is along the surface normal. We need to invert the vector
# using `math.scale` operator inwards in the geometry, to get the path
# direction.
#
normal_vec_in_field = ops.math.scale(field=normal_vec_out_field,
ponderation=-1.0)
normal_vec_in = normal_vec_in_field.outputs.field.get_data().data[0]
###############################################################################
# Get Nodal coordinates, they serve as the first point on the line.
#
node = mesh.nodes.node_by_id(node_id)
line_fp = node.coordinates
###############################################################################
# Create 3D line equation.
#
fx = lambda t: line_fp[0] + normal_vec_in[0] * t
fy = lambda t: line_fp[1] + normal_vec_in[1] * t
fz = lambda t: line_fp[2] + normal_vec_in[2] * t
###############################################################################
# Create coordinates using 3D line equation-
#
coordinates = [[fx(t * delta), fy(t * delta), fz(t * delta)] for t in
range(int(depth / delta))]
flat_coordinates = [entry for data in coordinates for entry in data]
###############################################################################
# Create Field for coordinates of the path.
#
field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates))
field_coord.data = flat_coordinates
field_coord.scoping.ids = list(range(1, len(coordinates) + 1))
###############################################################################
# Let's now map results on the path.
mapping_operator = ops.mapping.on_coordinates(
fields_container=stress_fc,
coordinates=field_coord,
create_support=True,
mesh=mesh)
fields_mapped = mapping_operator.outputs.fields_container()
###############################################################################
# Here, we request the mapped field data and its mesh
field_m = fields_mapped[0]
mesh_m = field_m.meshed_region
###############################################################################
# Create stress vs length chart.
#
x_initial = 0.0
length = [x_initial + delta * index for index in range(len(field_m.data))]
plt.plot(length, field_m.data, "r")
plt.xlabel("Length (%s)" % mesh.unit)
plt.ylabel("Stress (%s)" % field_m.unit)
plt.show()
###############################################################################
# To create a plot we need to add both the meshes
# `mesh_m` - mapped mesh
# `mesh` - original mesh
pl = DpfPlotter()
pl.add_field(field_m, mesh_m)
pl.add_mesh(mesh, style="surface", show_edges=True,
color="w", opacity=0.3)
pl.show_figure(show_axes=True, cpos=[
(62.687, 50.119, 67.247),
(5.135, 6.458, -0.355),
(-0.286, 0.897, -0.336)])
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

install_requires = ["psutil", "progressbar2", "numpy", "ansys.grpc.dpf>=0.2.3"]


# Get version from version info
filepath = os.path.dirname(__file__)
__version__ = None
Expand Down