|
| 1 | +# Copyright (C) 2023 - 2024 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 | +.. _thermal_example: |
| 25 | +
|
| 26 | +Thermal analysis |
| 27 | +---------------- |
| 28 | +
|
| 29 | +PyDPF Composites can also be used to post-process thermal analyses. |
| 30 | +In this case, the simulation is a two-step analysis where the results of |
| 31 | +a thermal analysis are an input of the structural analysis. So, the RST |
| 32 | +contains temperature and structural results. |
| 33 | +The example mimics a PCB which was modeled with Ansys Composites PrePost (ACP). |
| 34 | +where the solid model feature of ACP is used to generate the volume mesh. |
| 35 | +
|
| 36 | +In detail, the example shows how to extract the temperatures for a specific ply, |
| 37 | +and a specific material. |
| 38 | +
|
| 39 | +.. note:: |
| 40 | +
|
| 41 | + When using a Workbench project, |
| 42 | + use the :func:`.get_composite_files_from_workbench_result_folder` |
| 43 | + method to obtain the input files. |
| 44 | +
|
| 45 | +""" |
| 46 | + |
| 47 | +# %% |
| 48 | +# Set up analysis |
| 49 | +# ~~~~~~~~~~~~~~~ |
| 50 | +# Setting up the analysis consists of loading the required modules, connecting to the |
| 51 | +# DPF server, and retrieving the example files. |
| 52 | +# |
| 53 | +import ansys.dpf.core as dpf |
| 54 | +import numpy as np |
| 55 | + |
| 56 | +from ansys.dpf.composites.composite_model import CompositeModel |
| 57 | +from ansys.dpf.composites.constants import TEMPERATURE_COMPONENT |
| 58 | +from ansys.dpf.composites.example_helper import get_continuous_fiber_example_files |
| 59 | +from ansys.dpf.composites.layup_info import get_all_analysis_ply_names |
| 60 | +from ansys.dpf.composites.ply_wise_data import SpotReductionStrategy, get_ply_wise_data |
| 61 | +from ansys.dpf.composites.select_indices import get_selected_indices_by_dpf_material_ids |
| 62 | +from ansys.dpf.composites.server_helpers import connect_to_or_start_server |
| 63 | + |
| 64 | +server = connect_to_or_start_server() |
| 65 | +composite_files = get_continuous_fiber_example_files(server, "thermal_solid") |
| 66 | + |
| 67 | +# %% |
| 68 | +# Initialize the model |
| 69 | +# ~~~~~~~~~~~~~~~~~~~~ |
| 70 | +# The composite model is initialized with the composite files and the server. |
| 71 | +# It provides access to the mesh, results, lay-up and materials |
| 72 | +composite_model = CompositeModel(composite_files, server) |
| 73 | + |
| 74 | +# %% |
| 75 | +# Get Results - Temperatures |
| 76 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 77 | +# The temperatures are stored under structural_temperature |
| 78 | +temp_op = composite_model.core_model.results.structural_temperature() |
| 79 | +temperatures_fc = temp_op.outputs.fields_container() |
| 80 | + |
| 81 | +# %% |
| 82 | +# Ply-wise results |
| 83 | +# ~~~~~~~~~~~~~~~~ |
| 84 | +# Ply-wise results can be easily extracted using the function |
| 85 | +# :func:`.get_ply_wise_data` and by passing the ply name. |
| 86 | + |
| 87 | +all_ply_names = get_all_analysis_ply_names(composite_model.get_mesh()) |
| 88 | +print(all_ply_names) |
| 89 | + |
| 90 | +nodal_values = get_ply_wise_data( |
| 91 | + field=temperatures_fc, |
| 92 | + ply_name="P1L1__ModelingPly.8", |
| 93 | + mesh=composite_model.get_mesh(), |
| 94 | + component=TEMPERATURE_COMPONENT, |
| 95 | + spot_reduction_strategy=SpotReductionStrategy.MAX, |
| 96 | + requested_location=dpf.locations.nodal, |
| 97 | +) |
| 98 | + |
| 99 | +composite_model.get_mesh().plot(nodal_values) |
| 100 | + |
| 101 | +# %% |
| 102 | +# Material-wise results |
| 103 | +# ~~~~~~~~~~~~~~~~~~~~~ |
| 104 | +# It is also possible to filter the results by material. |
| 105 | +# In this example the element-wise maximum temperature |
| 106 | +# is extracted for the material `Honeycomb Aluminum Alloy`. |
| 107 | +print(composite_model.material_names) |
| 108 | +material_id = composite_model.material_names["Honeycomb Aluminum Alloy"] |
| 109 | + |
| 110 | +# get the last result field |
| 111 | +temperatures_field = temperatures_fc[-1] |
| 112 | + |
| 113 | +material_result_field = dpf.field.Field(location=dpf.locations.elemental, nature=dpf.natures.scalar) |
| 114 | +# performance optimization: use a local field instead of a field which is pushed to the server |
| 115 | +with material_result_field.as_local_field() as local_result_field: |
| 116 | + element_ids = temperatures_field.scoping.ids |
| 117 | + |
| 118 | + for element_id in element_ids: |
| 119 | + element_info = composite_model.get_element_info(element_id) |
| 120 | + assert element_info is not None |
| 121 | + if material_id in element_info.dpf_material_ids: |
| 122 | + temp_data = temperatures_field.get_entity_data_by_id(element_id) |
| 123 | + selected_indices = get_selected_indices_by_dpf_material_ids(element_info, [material_id]) |
| 124 | + |
| 125 | + value = np.max(temp_data[selected_indices]) |
| 126 | + local_result_field.append([value], element_id) |
| 127 | + |
| 128 | +composite_model.get_mesh().plot(material_result_field) |
0 commit comments