|
| 1 | +# Copyright (C) 2020 - 2025 ANSYS, Inc. and/or its affiliates. |
| 2 | +# SPDX-License-Identifier: MIT |
| 3 | +# |
| 4 | +# |
| 5 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | +# of this software and associated documentation files (the "Software"), to deal |
| 7 | +# in the Software without restriction, including without limitation the rights |
| 8 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | +# copies of the Software, and to permit persons to whom the Software is |
| 10 | +# furnished to do so, subject to the following conditions: |
| 11 | +# |
| 12 | +# The above copyright notice and this permission notice shall be included in all |
| 13 | +# copies or substantial portions of the Software. |
| 14 | +# |
| 15 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | +# SOFTWARE. |
| 22 | + |
| 23 | +""" |
| 24 | +.. _ref_matrix-operations: |
| 25 | +
|
| 26 | +Matrix Operations |
| 27 | +~~~~~~~~~~~~~~~~~ |
| 28 | +
|
| 29 | +This example shows how to do some matrix operations, including basic mathematical operations (power, add and multiply by |
| 30 | +a constant, add field containers and invert) and separating and assembling fields and fields containers. |
| 31 | +
|
| 32 | +""" |
| 33 | + |
| 34 | +############################################################################### |
| 35 | +# Import the ``ansys.dpf.core`` module, included examples file, and the ``operators.math`` |
| 36 | +# module. |
| 37 | +from ansys.dpf import core as dpf |
| 38 | +from ansys.dpf.core import examples |
| 39 | +import ansys.dpf.core.operators.math as maths |
| 40 | + |
| 41 | +############################################################################### |
| 42 | +# Open an example and print the ``Model`` object |
| 43 | +# The :class:`Model <ansys.dpf.core.model.Model>` class helps to organize access |
| 44 | +# methods for the result by keeping track of the operators and data sources |
| 45 | +# used by the result file. |
| 46 | +# |
| 47 | +# Printing the model displays this metadata: |
| 48 | +# |
| 49 | +# - Analysis type |
| 50 | +# - Available results |
| 51 | +# - Size of the mesh |
| 52 | +# - Number of results |
| 53 | +# |
| 54 | +my_model = dpf.Model(examples.find_complex_rst()) |
| 55 | +my_mesh = my_model.metadata.meshed_region |
| 56 | +print(my_model) |
| 57 | +############################################################################### |
| 58 | +# Get the stress tensor and define its scoping. Only three nodes will be taken into account to facilitate the |
| 59 | +# visualization. |
| 60 | +my_nodes_scoping = dpf.Scoping(ids=[38, 37, 36], location=dpf.locations.elemental) |
| 61 | +my_stress = my_model.results.stress(mesh_scoping=my_nodes_scoping).eval() |
| 62 | + |
| 63 | +# We need to average the result from 'elemental_nodal' to an 'elemental' location to plot it. |
| 64 | +my_avg_stress = dpf.operators.averaging.to_elemental_fc( |
| 65 | + fields_container=my_stress, mesh=my_mesh |
| 66 | +).eval() |
| 67 | +print(my_avg_stress) |
| 68 | +print(my_avg_stress[0]) |
| 69 | +######################################################### |
| 70 | +# Separating tensor by component |
| 71 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 72 | + |
| 73 | +# If operations need to be done separately in each tensor component, use |
| 74 | +# :func:'select_component()<ansys.dpf.core.fields_container.FieldsContainer.select_component>'. |
| 75 | +# Here, the stress tensor has 6 components per elementary data (symmetrical tensor XX,YY,ZZ,XY,YZ,XZ). |
| 76 | + |
| 77 | +# Separating the results in different fields containers for each stress tensor component |
| 78 | +stress_1 = my_avg_stress.select_component(0) |
| 79 | +stress_2 = my_avg_stress.select_component(1) |
| 80 | +stress_3 = my_avg_stress.select_component(2) |
| 81 | +stress_4 = my_avg_stress.select_component(3) |
| 82 | +stress_5 = my_avg_stress.select_component(4) |
| 83 | +stress_6 = my_avg_stress.select_component(5) |
| 84 | + |
| 85 | +################################################################################ |
| 86 | +# Mathematical operation on each field |
| 87 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 88 | + |
| 89 | +# Here we will do some basic mathematical operations on each stress field |
| 90 | + |
| 91 | +# Power |
| 92 | +# Raise each value of the field to power 2 |
| 93 | +stress_1 = maths.pow_fc(fields_container=stress_1, factor=2.0).eval() |
| 94 | + |
| 95 | +# Add a constant |
| 96 | +# Add 2 to each value in the field |
| 97 | +stress_2 = maths.add_constant_fc(fields_container=stress_2, ponderation=2.0).eval() |
| 98 | + |
| 99 | +# Multiply by a constant |
| 100 | +# Multiply each value in the field by 3 |
| 101 | +stress_3 = maths.scale_fc(fields_container=stress_3, ponderation=3.0).eval() |
| 102 | + |
| 103 | +# Add fields containers |
| 104 | +# Each value of each field is added by the correspondent component of the others fields |
| 105 | +stress_4 = maths.add_fc(fields_container1=stress_4, fields_container2=stress_5).eval() |
| 106 | +stress_5 = maths.add_fc(fields_container1=stress_5, fields_container2=stress_6).eval() |
| 107 | + |
| 108 | +# Invert |
| 109 | +# Compute the invert of each element of each field (1./X) |
| 110 | +stress_6 = maths.invert_fc(fields_container=stress_6).eval() |
| 111 | + |
| 112 | +################################################################################ |
| 113 | +# Reassembling the stress tensor |
| 114 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 115 | + |
| 116 | +# There are different methods to re-assemble the components, here we use the |
| 117 | +# operator :class:'assemble_scalars_to_matrices_fc <ansys.dpf.core.operators.utility.assemble_scalars_to_matrices_fc.assemble_scalars_to_matrices_fc>' |
| 118 | + |
| 119 | +re_assemble = dpf.operators.utility.assemble_scalars_to_matrices_fc( |
| 120 | + xx=stress_1, yy=stress_2, zz=stress_3, xy=stress_4, yz=stress_5, xz=stress_6, symmetrical=True |
| 121 | +).eval() |
| 122 | + |
| 123 | +print(re_assemble) |
| 124 | +print(re_assemble[0]) |
0 commit comments