24using JsonObject = boost::json::object;
28 const std::string &local_error) {
31 CHKERR MPI_Comm_rank(comm, &rank);
32 CHKERR MPI_Comm_size(comm, &mpi_size);
33 const int local_rank = local_error.empty() ? mpi_size : rank;
34 int error_rank = mpi_size;
35 CHKERR MPI_Allreduce(&local_rank, &error_rank, 1, MPI_INT, MPI_MIN, comm);
36 if (error_rank != mpi_size) {
38 if (rank == error_rank)
39 message = local_error.substr(0, 16384);
40 int length =
static_cast<int>(message.size());
41 CHKERR MPI_Bcast(&length, 1, MPI_INT, error_rank, comm);
42 message.resize(length);
43 CHKERR MPI_Bcast(message.data(), length, MPI_CHAR, error_rank, comm);
53 CHKERR checkCollectiveLayoutError(
56 :
"Restart layout requires an elastic DM and vector");
57 int comparison = MPI_UNEQUAL;
59 comm, PetscObjectComm(
reinterpret_cast<PetscObject
>(
state)), &comparison);
60 CHKERR checkCollectiveLayoutError(
61 comm, comparison == MPI_IDENT || comparison == MPI_CONGRUENT
63 :
"Restart vector and elastic DM use different communicators");
66 CHKERR MPI_Comm_size(comm, &mpi_size);
67 PetscInt global_size, local_size;
70 std::vector<PetscInt> partition_sizes(mpi_size);
71 CHKERR MPI_Allgather(&local_size, 1, MPIU_INT, partition_sizes.data(), 1,
73 boost::json::array partitions;
74 for (
const auto size : partition_sizes)
75 partitions.emplace_back(static_cast<
std::int64_t>(size));
77 const Problem *problem_ptr =
nullptr;
79 CHKERR checkCollectiveLayoutError(
82 :
"Restart elastic DM has no numbered row DOFs");
83 CHKERR checkCollectiveLayoutError(
86 :
"Restart vector size differs from the elastic DM layout");
89 layout[
"version"] = 1;
90 layout[
"formulation"] =
92 ?
"auxiliary_logarithmic_stress"
100 :
static_cast<int>(material_model);
102 layout[
"stretch_handling"] =
108 layout[
"rotation_selector"] =
static_cast<int>(ep.
rotSelector);
112 layout[
"vector_global_size"] =
static_cast<std::int64_t
>(global_size);
113 layout[
"mpi_ranks"] = mpi_size;
114 layout[
"vector_partition_sizes"] = std::move(partitions);
116 std::set<std::string> field_names;
117 for (
const auto &dof : *problem_ptr->getNumeredRowDofsPtr())
118 if (dof->getPetscGlobalDofIdx() >= 0)
119 field_names.insert(dof->getName());
120 std::string local_names;
121 for (
const auto &name : field_names)
122 local_names += name +
'\n';
123 CHKERR checkCollectiveLayoutError(
124 comm, local_names.size() <= std::numeric_limits<int>::max()
126 :
"Restart field names exceed the MPI metadata size limit");
127 const int local_length =
static_cast<int>(local_names.size());
128 std::vector<int> lengths(mpi_size), offsets(mpi_size);
129 CHKERR MPI_Allgather(&local_length, 1, MPI_INT, lengths.data(), 1, MPI_INT,
131 std::size_t total_length = 0;
132 for (
int rank = 0; rank != mpi_size; ++rank) {
133 offsets[rank] =
static_cast<int>(total_length);
134 total_length += lengths[rank];
136 CHKERR checkCollectiveLayoutError(
137 comm, total_length <= std::numeric_limits<int>::max()
139 :
"Restart field layout exceeds the MPI metadata size limit");
140 std::string all_names(total_length,
'\0');
141 CHKERR MPI_Allgatherv(local_names.data(), local_length, MPI_CHAR,
142 all_names.data(), lengths.data(), offsets.data(),
144 std::istringstream names_stream(all_names);
145 for (std::string name; std::getline(names_stream, name);)
147 field_names.insert(name);
149 const auto material_fields =
151 boost::json::array material_names;
152 for (
const auto &field : material_fields) {
155 CHKERR checkCollectiveLayoutError(
156 comm, field_names.count(field.name)
158 :
"Restart material field has no active DOFs: " + field.name);
159 material_names.emplace_back(field.name);
161 layout[
"material_fields"] = std::move(material_names);
163 boost::json::array fields;
167 :
"Restart field is missing: " +
174 PetscInt field_size, local_field_size;
175 CHKERR ISGetSize(field_is, &field_size);
176 CHKERR ISGetLocalSize(field_is, &local_field_size);
179 const PetscInt *indices =
nullptr;
180 CHKERR ISGetIndices(field_is, &indices);
181 int minimum_order = std::numeric_limits<int>::max();
182 int maximum_order = -1;
183 std::string local_error;
184 for (PetscInt
n = 0;
n != local_field_size; ++
n) {
185 const auto dof = dofs.find(indices[
n]);
186 if (dof == dofs.end()) {
187 local_error =
"Restart DM is missing a numbered DOF of " +
field_name;
190 const int order = (*dof)->getDofOrder();
191 minimum_order = std::min(minimum_order,
order);
192 maximum_order = std::max(maximum_order,
order);
194 CHKERR ISRestoreIndices(field_is, &indices);
195 CHKERR checkCollectiveLayoutError(comm, local_error);
196 CHKERR MPI_Allreduce(MPI_IN_PLACE, &minimum_order, 1, MPI_INT, MPI_MIN,
198 CHKERR MPI_Allreduce(MPI_IN_PLACE, &maximum_order, 1, MPI_INT, MPI_MAX,
200 CHKERR checkCollectiveLayoutError(
201 comm, field_size > 0 && minimum_order >= 0
203 :
"Restart field has no active DOFs: " +
field_name);
207 {
"components",
static_cast<int>(field_ptr->getNbOfCoeffs())},
208 {
"space", field_ptr->getSpaceName()},
209 {
"basis", field_ptr->getApproxBaseName()},
210 {
"continuity", field_ptr->getContinuityName()},
211 {
"minimum_dof_order", minimum_order},
212 {
"maximum_dof_order", maximum_order},
213 {
"global_dofs",
static_cast<std::int64_t
>(field_size)}};
214 const auto material_field = std::find_if(
215 material_fields.begin(), material_fields.end(), [&](
const auto &entry) {
216 return entry.order >= 0 && entry.name == field_name;
218 if (material_field != material_fields.end()) {
219 field[
"order_policy"] =
"FieldOrders::stretch(space_order)";
220 field[
"requested_order"] = material_field->order;
222 fields.emplace_back(std::move(field));
224 layout[
"fields"] = std::move(fields);
228std::string compareRestartLayout(
const boost::json::value &stored,
229 const JsonObject &expected,
230 const std::string &file_name) {
231 if (!stored.is_object())
232 return "Restart metadata is not a JSON object: " + file_name;
233 const auto &
object = stored.as_object();
234 for (
const auto &entry : expected) {
235 const auto stored_value =
object.if_contains(entry.key());
236 if (!stored_value || *stored_value != entry.value())
237 return "Restart layout mismatch for '" +
238 std::string(entry.key().data(), entry.key().size()) +
"' in " +
240 "; use the formulation, fields, orders and MPI partition of the "
241 "saved native restart";
243 if (
object.size() != expected.size())
244 return "Unexpected entries in restart layout metadata: " + file_name;
251 const std::string &binary_file) {
257 CHKERR MPI_Comm_rank(comm, &rank);
258 const std::string file_name = binary_file +
".layout.json";
259 std::string local_error;
261 const std::string temporary_file = file_name +
".tmp";
263 std::ofstream output(temporary_file, std::ios::out | std::ios::trunc);
264 output << boost::json::serialize(layout) <<
'\n';
266 const bool written = output.good();
268 if (!written || output.fail())
269 local_error =
"Cannot write restart layout metadata: " + file_name;
270 else if (std::rename(temporary_file.c_str(), file_name.c_str()))
271 local_error =
"Cannot install restart layout metadata " + file_name +
272 ": " + std::strerror(errno);
273 }
catch (
const std::exception &error) {
274 local_error =
"Cannot write restart layout metadata " + file_name +
": " +
277 if (!local_error.empty())
278 std::remove(temporary_file.c_str());
280 CHKERR checkCollectiveLayoutError(comm, local_error);
285 const std::string &binary_file) {
289 CHKERR MPI_Comm_rank(comm, &rank);
290 const std::string file_name = binary_file +
".layout.json";
292 std::string contents, local_error;
295 std::error_code error;
296 exists = std::filesystem::exists(file_name, error);
298 local_error =
"Cannot inspect restart layout metadata " + file_name +
299 ": " + error.message();
301 std::ifstream input(file_name);
302 std::ostringstream buffer;
303 buffer << input.rdbuf();
304 if (!input.is_open() || input.bad() || buffer.fail())
305 local_error =
"Cannot read restart layout metadata: " + file_name;
307 contents = buffer.str();
308 if (contents.size() >
309 static_cast<std::size_t
>(std::numeric_limits<int>::max()))
310 local_error =
"Restart layout metadata is too large: " + file_name;
312 }
catch (
const std::exception &error) {
313 local_error =
"Cannot read restart layout metadata " + file_name +
": " +
317 CHKERR checkCollectiveLayoutError(comm, local_error);
318 CHKERR MPI_Bcast(&exists, 1, MPI_INT, 0, comm);
320 CHKERR checkCollectiveLayoutError(
323 ?
"Auxiliary logarithmic-stress restart requires " +
325 "; an old raw stretch vector cannot be loaded into "
326 "the D/theta/Td fields"
331 int length =
static_cast<int>(contents.size());
332 CHKERR MPI_Bcast(&length, 1, MPI_INT, 0, comm);
333 contents.resize(length);
334 CHKERR MPI_Bcast(contents.data(), length, MPI_CHAR, 0, comm);
338 boost::system::error_code parse_error;
339 const auto stored = boost::json::parse(contents, parse_error);
340 local_error = parse_error
341 ?
"Invalid restart layout JSON in " + file_name +
": " +
342 parse_error.message()
343 : compareRestartLayout(stored, expected, file_name);
344 }
catch (
const std::exception &error) {
345 local_error =
"Cannot validate restart layout metadata " + file_name +
348 CHKERR checkCollectiveLayoutError(comm, local_error);
Eshelbian plasticity interface.
Native restart vector layout validation.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
static const char *const ApproximationBaseNames[]
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMMoFEMGetProblemPtr(DM dm, const MoFEM::Problem **problem_ptr)
Get pointer to problem data structure.
PetscErrorCode DMMoFEMGetFieldIS(DM dm, RowColData rc, const char field_name[], IS *is)
get field is in the problem
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual bool check_field(const std::string &name) const =0
check if field is in database
const double n
refractive index of diffusive medium
MoFEM::MoFEMErrorCode writeRestartLayout(const EshelbianCore &ep, Vec state, const std::string &binary_file)
MoFEM::MoFEMErrorCode validateRestartLayout(const EshelbianCore &ep, Vec state, const std::string &binary_file)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
constexpr auto field_name
static enum StretchSelector stretchSelector
MoFEM::Interface & mField
static PetscBool l2UserBaseScale
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static FieldApproximationBase brokenHdivBase
boost::shared_ptr< PhysicalEquations > physicalEquations
SmartPetscObj< DM > dmElastic
Elastic problem.
static const Features noStretchMask
@ NO_STRETCH_LINEAR
No-stretch linear formulation.
@ AUXILIARY_LOGARITHMIC_STRESS
Auxiliary logarithmic stress formulation.
@ NO_STRETCH_NONLINEAR
No-stretch nonlinear formulation.
virtual MPI_Comm & get_comm() const =0
keeps basic data about problem
DofIdx getNbDofsRow() const
auto & getNumeredRowDofsPtr() const
get access to numeredRowDofsPtr storing DOFs on rows
intrusive_ptr for managing petsc objects