https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FileMeshComponent.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "FileMeshComponent.h"
11#include "THMMesh.h"
12#include "MooseUtils.h"
13#include "libmesh/exodusII_io.h"
14#include "libmesh/exodusII_io_helper.h"
15
16registerMooseObject("ThermalHydraulicsApp", FileMeshComponent);
17
20{
22
23 params.addRequiredParam<FileName>("file", "The ExodusII mesh file name");
24 params.addRequiredParam<Point>("position", "Translation vector for the file mesh [m]");
25
26 params.addClassDescription("Loads a mesh from an ExodusII file without adding physics.");
27
28 return params;
29}
30
32 : GeometricalComponent(parameters),
33 _file_name(getParam<FileName>("file")),
34 _file_is_readable(MooseUtils::pathExists(_file_name) &&
35 MooseUtils::checkFileReadable(_file_name, false, false)),
36 _position(getParam<Point>("position"))
37{
38 // The following is a mooseError instead of logError because the 'add_variable'
39 // and 'add_aux_variable' tasks must execute before the integrity check, so if
40 // the file is unreadable, the user would just get an error message about variables
41 // being added to non-existent blocks.
43 mooseError("The file '",
45 "' could not be opened. Check that the file exists and that "
46 "you have permission to open it.");
47}
48
49void
51{
53 {
54 buildMesh();
55
56 // apply translation vector to all nodes
57 for (auto && node_id : _node_ids)
58 {
59 Node & node = mesh().nodeRef(node_id);
60 RealVectorValue p(node(0), node(1), node(2));
61 node = p + _position;
62 }
63 }
64}
65
66std::vector<std::string>
68{
69 std::vector<std::string> subdomain_names;
70
71 auto & thm_mesh = mesh();
72
73 libMesh::ExodusII_IO_Helper exio_helper(*this, false, true, false);
74 exio_helper.open(_file_name.c_str(), true);
75 exio_helper.read_and_store_header_info();
76
77 // maps from Exodus IDs to THMMesh IDs
78 std::map<int, unsigned int> node_id_map;
79 std::map<int, unsigned int> elem_id_map;
80 std::map<int, unsigned int> boundary_id_map;
81
82 // Loop over nodes:
83 // - Add the nodes into THMMesh
84 // - Populate node_id_map
85 exio_helper.read_nodes();
86 exio_helper.read_node_num_map();
87 for (int i = 0; i < exio_helper.num_nodes; i++)
88 {
89 int exodus_id = exio_helper.node_num_map[i];
90
91 Point p(exio_helper.x[i], exio_helper.y[i], exio_helper.z[i]);
92 const Node * node = addNode(p);
93 node_id_map[exodus_id] = node->id();
94 }
95
96 // Loop over blocks:
97 // - Populate subdomain_names
98 // - Set the blocks in THMMesh
99 // - Add the elements into THMMesh
100 exio_helper.read_block_info();
101 exio_helper.read_elem_num_map();
102 int jmax_last_block = 0;
103 for (int i = 0; i < exio_helper.num_elem_blk; i++)
104 {
105 exio_helper.read_elem_in_block(i);
106
107 // Get subdomain name from file (or ID if no name) and populate subdomain_names
108 std::string subdomain_name = exio_helper.get_block_name(i);
109 if (subdomain_name.empty())
110 subdomain_name = Moose::stringify(exio_helper.get_block_id(i));
111 subdomain_names.push_back(subdomain_name);
112
113 // Generate the subdomain name and ID for THMMesh, and set them
114 const std::string component_subdomain_name = genName(_name, subdomain_name);
115 SubdomainID sid = thm_mesh.getNextSubdomainId();
116 setSubdomainInfo(sid, component_subdomain_name, Moose::COORD_XYZ);
117
118 const std::string type_str(exio_helper.get_elem_type());
119 const auto & conv = exio_helper.get_conversion(type_str);
120
121 // Loop over elements in block
122 int jmax = jmax_last_block + exio_helper.num_elem_this_blk;
123 for (int j = jmax_last_block; j < jmax; j++)
124 {
125 // Loop over nodes on element:
126 // - Get the node IDs on the element
127 std::vector<dof_id_type> node_ids(exio_helper.num_nodes_per_elem);
128 for (int k = 0; k < exio_helper.num_nodes_per_elem; k++)
129 {
130 int gi = (j - jmax_last_block) * exio_helper.num_nodes_per_elem + conv.get_node_map(k);
131 int ex_node_id = exio_helper.node_num_map[exio_helper.connect[gi] - 1];
132 node_ids[k] = node_id_map[ex_node_id];
133 }
134
135 // Add the element and set its subdomain
136 Elem * elem = addElement(conv.libmesh_elem_type(), node_ids);
137 elem->subdomain_id() = sid;
138
139 // Populate elem_id_map
140 int exodus_id = exio_helper.elem_num_map[j];
141 elem_id_map[exodus_id] = elem->id();
142 }
143 jmax_last_block += exio_helper.num_elem_this_blk;
144 }
145
146 // Loop over boundaries:
147 // - Get the Exodus boundary names and store them
148 // - Generate the boundary IDs
149 exio_helper.read_sideset_info();
150 int offset = 0;
151 std::unordered_map<BoundaryID, BoundaryName> new_ids_to_names;
152 for (int i = 0; i < exio_helper.num_side_sets; i++)
153 {
154 // Compute new offset
155 offset += (i > 0 ? exio_helper.num_sides_per_set[i - 1] : 0);
156 exio_helper.read_sideset(i, offset);
157
158 // Get boundary name from file (or ID if no name)
159 int ex_sideset_id = exio_helper.get_side_set_id(i);
160 std::string sideset_name = exio_helper.get_side_set_name(i);
161 if (sideset_name.empty())
162 sideset_name = Moose::stringify(ex_sideset_id);
163
164 // Generate the boundary ID for THMMesh and populate boundary_id_map
165 unsigned int bc_id = thm_mesh.getNextBoundaryId();
166 boundary_id_map[ex_sideset_id] = bc_id;
167 new_ids_to_names.emplace(bc_id, genName(_name, sideset_name));
168 }
169
170 auto & boundary_info = thm_mesh.getMesh().get_boundary_info();
171
172 // Loop over the elements on boundaries
173 // Add the boundary elem/side pairs to the boundary
174 for (auto e : index_range(exio_helper.elem_list))
175 {
176 // Get the element
177 int ex_elem_id = exio_helper.elem_num_map[exio_helper.elem_list[e] - 1];
178 dof_id_type elem_id = elem_id_map[ex_elem_id];
179 Elem * elem = thm_mesh.elemPtr(elem_id);
180
181 // Get the side index
182 const auto & conv = exio_helper.get_conversion(elem->type());
183 // Map the zero-based Exodus side numbering to the libmesh side numbering
184 unsigned int raw_side_index = exio_helper.side_list[e] - 1;
185 std::size_t side_index_offset = conv.get_shellface_index_offset();
186 unsigned int side_index = static_cast<unsigned int>(raw_side_index - side_index_offset);
187 int mapped_side = conv.get_side_map(side_index);
188
189 // Get the boundary ID and add the elem/side pair to the boundary
190 unsigned int bc_id = boundary_id_map[exio_helper.id_list[e]];
191 boundary_info.add_side(elem, mapped_side, bc_id);
192 _boundary_info[new_ids_to_names[bc_id]].push_back(
193 std::tuple<dof_id_type, unsigned short int>(elem->id(), mapped_side));
194 }
195
196 // Generate and set the boundary name
197 for (const auto & id_and_name : new_ids_to_names)
198 {
199 boundary_info.sideset_name(id_and_name.first) = id_and_name.second;
200 boundary_info.nodeset_name(id_and_name.first) = id_and_name.second;
201 _boundary_names.push_back(id_and_name.second);
202 }
203
204 // This appears to be necessary to get the nodesets named correctly, despite
205 // the fact that it gets called later.
206 boundary_info.build_node_list_from_side_list();
207
208 return subdomain_names;
209}
210
211bool
212FileMeshComponent::hasBoundary(const BoundaryName & boundary_name) const
213{
215
216 return std::find(_boundary_names.begin(), _boundary_names.end(), boundary_name) !=
217 _boundary_names.end();
218}
219
220const std::vector<std::tuple<dof_id_type, unsigned short int>> &
221FileMeshComponent::getBoundaryInfo(const BoundaryName & boundary_name) const
222{
224
225 if (_boundary_info.find(boundary_name) != _boundary_info.end())
226 return _boundary_info.at(boundary_name);
227 else
229 ": No boundary info exists for the boundary '",
230 boundary_name,
231 "' on this component.");
232}
registerMooseObject("ThermalHydraulicsApp", FileMeshComponent)
const Real p
const std::string name
Definition Setup.h:21
Node * addNode(const Point &pt)
Definition Component.C:203
virtual void setSubdomainInfo(SubdomainID subdomain_id, const std::string &subdomain_name, const Moose::CoordinateSystemType &coord_system=Moose::COORD_XYZ)
Sets the next subdomain ID, name, and coordinate system.
Definition Component.C:219
@ MESH_PREPARED
mesh set up
Definition Component.h:40
std::vector< dof_id_type > _node_ids
Node IDs of this component.
Definition Component.h:506
void checkSetupStatus(const EComponentSetupStatus &status) const
Throws an error if the supplied setup status of this component has not been reached.
Definition Component.C:117
THMMesh & mesh()
Non-const reference to THM mesh, which can only be called before the end of mesh setup.
Definition Component.C:60
Loads a mesh from an ExodusII file without adding physics.
std::map< BoundaryName, std::vector< std::tuple< dof_id_type, unsigned short int > > > _boundary_info
Map of boundary name to list of tuples of element and side IDs for that boundary.
bool hasBoundary(const BoundaryName &boundary_name) const
Returns true if this component has the supplied boundary.
const Point & _position
Translation vector for the file mesh.
FileMeshComponent(const InputParameters &parameters)
virtual void setupMesh() override
Performs mesh setup such as creating mesh or naming mesh sets.
const std::vector< std::tuple< dof_id_type, unsigned short int > > & getBoundaryInfo(const BoundaryName &boundary_name) const
Gets boundary info associated with the component boundary.
const FileName & _file_name
The name of the ExodusII file to load the mesh from.
std::vector< BoundaryName > _boundary_names
Boundary names for this component.
std::vector< std::string > buildMesh()
Loads the ExodusII file into the global mesh and returns the subdomain names (before prepending compo...
static InputParameters validParams()
const bool _file_is_readable
Is the file readable?
Intermediate class for components that have mesh.
static InputParameters validParams()
Elem * addElement(libMesh::ElemType elem_type, const std::vector< dof_id_type > &node_ids)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void mooseError(Args &&... args) const
const std::string & _name
virtual const Node & nodeRef(const dof_id_type i) const
std::string genName(const std::string &prefix, unsigned int id, const std::string &suffix="") const
Build a name from a prefix, number and possible suffix.
std::vector< Real > x
std::vector< int > id_list
std::string get_block_name(int index)
std::vector< int > side_list
std::vector< Real > z
const char * get_elem_type() const
std::vector< int > node_num_map
int get_side_set_id(int index)
void read_sideset(int id, int offset)
std::vector< int > elem_list
std::vector< Real > y
std::vector< int > num_sides_per_set
void open(const char *filename, bool read_only)
std::vector< int > connect
const ExodusII_IO_Helper::Conversion & get_conversion(const ElemType type) const
std::string get_side_set_name(int index)
void read_elem_in_block(int block)
std::vector< int > elem_num_map
std::string stringify(const T &t)