Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
mesh.cpp
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
7 #include "smith/physics/mesh.hpp"
8 
9 #include <format>
10 #include <memory>
11 #include <utility>
12 
13 #include <axom/slic.hpp>
14 
19 
20 namespace smith {
21 
22 Mesh::Mesh(const std::string& meshfile, const std::string& meshtag, int refine_serial, int refine_parallel,
23  MPI_Comm comm)
24  : mesh_tag_(meshtag)
25 {
26  auto meshtmp = mesh::refineAndDistribute(buildMeshFromFile(meshfile), refine_serial, refine_parallel, comm);
27  mfem_mesh_ = &smith::StateManager::setMesh(std::move(meshtmp), mesh_tag_);
28  notifyIfRankHasNoElements();
29  createDomains();
30 }
31 
32 Mesh::Mesh(mfem::Mesh&& mesh, const std::string& meshtag, int refine_serial, int refine_parallel, MPI_Comm comm)
33  : mesh_tag_(meshtag)
34 {
35  auto meshtmp = smith::mesh::refineAndDistribute(std::move(mesh), refine_serial, refine_parallel, comm);
36  mfem_mesh_ = &smith::StateManager::setMesh(std::move(meshtmp), mesh_tag_);
37  notifyIfRankHasNoElements();
38  createDomains();
39 }
40 
41 Mesh::Mesh(mfem::ParMesh&& mesh, const std::string& meshtag) : mesh_tag_(meshtag)
42 {
43  auto meshtmp = std::make_unique<mfem::ParMesh>(std::move(mesh));
44  meshtmp->EnsureNodes();
45  meshtmp->ExchangeFaceNbrData();
46  mfem_mesh_ = &smith::StateManager::setMesh(std::move(meshtmp), mesh_tag_);
47  notifyIfRankHasNoElements();
48  createDomains();
49 }
50 
51 void Mesh::notifyIfRankHasNoElements() const
52 {
53  int myRank, numRanks;
54  MPI_Comm_rank(getComm(), &myRank);
55  MPI_Comm_size(getComm(), &numRanks);
56  int rankHasNoElements = (0 == mfem_mesh_->GetNE()) ? 1 : 0;
57  ::std::vector<int> gatheredRankData((0 == myRank) ? static_cast<::std::size_t>(numRanks) : 0);
58  MPI_Gather(&rankHasNoElements, 1, MPI_INT, gatheredRankData.data(), 1, MPI_INT, 0, getComm());
59  if (0 == myRank) {
60  ::std::vector<::std::size_t> ranksWithNoElements;
61  for (::std::size_t i = 0; i < static_cast<::std::size_t>(numRanks); ++i) {
62  if (1 == gatheredRankData[i]) {
63  ranksWithNoElements.push_back(i);
64  }
65  }
66  if (0 < ranksWithNoElements.size()) {
67  ::std::ostringstream msg;
68  msg << "\nAfter refining and distributing mesh, the following " << ranksWithNoElements.size()
69  << " ranks own zero elements:\n[";
70  for (const ::std::size_t& rank : ranksWithNoElements) {
71  msg << " " << rank;
72  }
73  msg << "]\n";
74  SLIC_INFO(msg.str());
75  }
76  }
77  ::axom::slic::flushStreams();
78 }
79 
80 MPI_Comm Mesh::getComm() const { return mfem_mesh_->GetComm(); }
81 
82 void Mesh::createDomains()
83 {
84  domains_.insert({entireBodyName(), smith::EntireDomain(*mfem_mesh_)});
85  domains_.insert({entireBoundaryName(), smith::EntireBoundary(*mfem_mesh_)});
86  domains_.insert({internalBoundaryName(), smith::EntireInteriorBoundary(*mfem_mesh_)});
87 }
88 
89 void Mesh::errorIfDomainExists(const std::string& domain_name) const
90 {
91  SLIC_ERROR_IF(domains_.find(domain_name) != domains_.end(),
92  std::format("A domain named {0} already exists in mesh with tag {1}", domain_name, mesh_tag_));
93 }
94 
96 
98 
100 
101 void Mesh::insertDomain(const std::string& domain_name, const Domain& domain)
102 {
103  SLIC_ERROR_IF(&this->mfemParMesh() != &domain.mesh_, "A domain inserted onto a mesh must be defined on that mesh");
104  errorIfDomainExists(domain_name);
105  domains_.insert({domain_name, domain});
106 }
107 
108 smith::Domain& Mesh::domain(const std::string& domain_name) const
109 {
110  SLIC_ERROR_IF(domains_.find(domain_name) == domains_.end(),
111  std::format("Could not find domain named {0} in mesh with tag {1}", domain_name, mesh_tag_));
112  return domains_.at(domain_name);
113 }
114 
115 smith::Domain& Mesh::addDomainOfBoundaryElements(const std::string& domain_name,
116  std::function<bool(std::vector<vec2>, int)> func)
117 {
118  errorIfDomainExists(domain_name);
119  domains_.emplace(domain_name, Domain::ofBoundaryElements(*mfem_mesh_, func));
120  return domain(domain_name);
121 }
122 
123 smith::Domain& Mesh::addDomainOfBoundaryElements(const std::string& domain_name,
124  std::function<bool(std::vector<vec3>, int)> func)
125 {
126  errorIfDomainExists(domain_name);
127  domains_.emplace(domain_name, Domain::ofBoundaryElements(*mfem_mesh_, func));
128  return domain(domain_name);
129 }
130 
132  std::function<bool(std::vector<vec2>, int)> func)
133 {
134  errorIfDomainExists(domain_name);
135  domains_.emplace(domain_name, Domain::ofInteriorBoundaryElements(*mfem_mesh_, func));
136  return domain(domain_name);
137 }
138 
140  std::function<bool(std::vector<vec3>, int)> func)
141 {
142  errorIfDomainExists(domain_name);
143  domains_.emplace(domain_name, Domain::ofInteriorBoundaryElements(*mfem_mesh_, func));
144  return domain(domain_name);
145 }
146 
147 smith::Domain& Mesh::addDomainOfBodyElements(const std::string& domain_name,
148  std::function<bool(std::vector<vec2>, int)> func)
149 {
150  errorIfDomainExists(domain_name);
151  domains_.emplace(domain_name, Domain::ofElements(*mfem_mesh_, func));
152  return domain(domain_name);
153 }
154 
155 smith::Domain& Mesh::addDomainOfBodyElements(const std::string& domain_name,
156  std::function<bool(std::vector<vec3>, int)> func)
157 {
158  errorIfDomainExists(domain_name);
159  domains_.emplace(domain_name, Domain::ofElements(*mfem_mesh_, func));
160  return domain(domain_name);
161 }
162 
163 const mfem::ParFiniteElementSpace& Mesh::shapeDisplacementSpace()
164 {
166 }
167 
169 
171 
172 } // namespace smith
Class for encapsulating the dual vector space of a finite element space (i.e. the space of linear for...
Class for encapsulating the critical MFEM components of a primal finite element field.
mfem::ParFiniteElementSpace & space()
Returns a non-owning reference to the internal FESpace.
void insertDomain(const std::string &domain_name, const Domain &domain)
Insert a domain onto mesh.
Definition: mesh.cpp:101
smith::Domain & entireBody() const
Returns domain corresponding to the entire mesh.
Definition: mesh.cpp:95
smith::FiniteElementDual newShapeDisplacementDual()
create new shape displacement sensitivity
Definition: mesh.cpp:170
smith::Domain & domain(const std::string &domain_name) const
Returns registered domain with specified name.
Definition: mesh.cpp:108
const mfem::ParFiniteElementSpace & shapeDisplacementSpace()
get space associated with shape displacement
Definition: mesh.cpp:163
smith::Domain & addDomainOfBodyElements(const std::string &domain_name, std::function< bool(std::vector< vec3 >, int)> func)
create domain of 3D elements with specified name The second argument is a function taking a std::vect...
Definition: mesh.cpp:155
static std::string entireBodyName()
Returns string, name used to access the entire domain body.
Definition: mesh.hpp:75
smith::Domain & internalBoundary() const
Returns domain boundary corresponding to the internal boundary elements.
Definition: mesh.cpp:99
static std::string internalBoundaryName()
Returns string, name used to access the internal boundary elements.
Definition: mesh.hpp:87
smith::FiniteElementState newShapeDisplacement()
create new shape displacement
Definition: mesh.cpp:168
MPI_Comm getComm() const
Returns parallel communicator.
Definition: mesh.cpp:80
smith::Domain & entireBoundary() const
Returns domain boundary corresponding to the entire mesh.
Definition: mesh.cpp:97
const std::string & tag() const
Returns string tag for mesh.
Definition: mesh.hpp:63
const mfem::ParMesh & mfemParMesh() const
Returns const parallel mfem mesh.
Definition: mesh.hpp:66
smith::Domain & addDomainOfInternalBoundaryElements(const std::string &domain_name, std::function< bool(std::vector< vec3 >, int)> func)
create domain of 3D internal boundary elements with specified name The second argument is a function ...
Definition: mesh.cpp:139
Mesh(mfem::Mesh &&mesh, const std::string &meshtag, int serial_refine=0, int parallel_refine=0, MPI_Comm comm=MPI_COMM_WORLD)
Construct from existing serial mfem mesh.
Definition: mesh.cpp:32
static std::string entireBoundaryName()
Returns string, name used to access the entire boundary.
Definition: mesh.hpp:81
smith::Domain & addDomainOfBoundaryElements(const std::string &domain_name, std::function< bool(std::vector< vec3 >, int)> func)
create domain of 3D boundary elements with specified name The second argument is a function taking a ...
Definition: mesh.cpp:123
static FiniteElementState & shapeDisplacement(const std::string &mesh_tag)
Get the shape displacement finite element state.
static mfem::ParMesh & setMesh(std::shared_ptr< mfem::ParMesh > pmesh, const std::string &mesh_tag)
Shares ownership of mesh with StateManager.
static FiniteElementDual & shapeDisplacementDual(const std::string &mesh_tag)
Get the shape displacement finite element dual.
This file contains helper traits and enumerations for classifying finite elements.
This contains a class that represents the dual of a finite element vector space, i....
Smith mesh class which assists in constructing the appropriate parallel mfem meshes and registering a...
This file contains helper functions for importing and managing various mesh objects.
std::unique_ptr< mfem::ParMesh > refineAndDistribute(mfem::Mesh &&serial_mesh, const int refine_serial, const int refine_parallel, const MPI_Comm comm)
Finalizes a serial mesh into a refined parallel mesh.
Definition: mesh_utils.cpp:464
Accelerator functionality.
Definition: smith.cpp:36
Domain EntireInteriorBoundary(const mesh_t &mesh)
constructs a domain from all the interior boundary elements in a mesh
Definition: domain.cpp:626
Domain EntireBoundary(const mesh_t &mesh)
constructs a domain from all the boundary elements in a mesh
Definition: domain.cpp:610
Domain EntireDomain(const mesh_t &mesh)
constructs a domain from all the elements in a mesh
Definition: domain.cpp:595
mfem::Mesh buildMeshFromFile(const std::string &mesh_file)
Constructs an MFEM mesh from a file.
Definition: mesh_utils.cpp:25
This file contains the declaration of the StateManager class.
a class for representing a geometric region that can be used for integration
Definition: domain.hpp:33
static Domain ofElements(const mesh_t &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the elements (spatial dim == geometry dim) in an mfem::Mesh
Definition: domain.cpp:258
static Domain ofBoundaryElements(const mesh_t &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the boundary elements (spatial dim == geometry dim + 1) in an mfe...
Definition: domain.cpp:368
static Domain ofInteriorBoundaryElements(const mesh_t &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the interior boundary elements in an a mesh
Definition: domain.cpp:729
const mesh_t & mesh_
the underyling mesh for this domain
Definition: domain.hpp:45