20 #include "axom/core.hpp"
36 #include "serac/serac_config.hpp"
48 inlet.addDouble(
"t_final",
"Final time for simulation.").defaultValue(1.0);
49 inlet.addDouble(
"dt",
"Time step.").defaultValue(0.25);
52 auto& mesh_table = inlet.addStruct(
"main_mesh",
"The main mesh for the problem");
56 auto& solid_solver_table = inlet.addStruct(
"solid",
"Finite deformation solid mechanics module");
60 auto& thermal_solver_table = inlet.addStruct(
"heat_transfer",
"Heat transfer module");
64 auto& thermal_solid_solver_table = inlet.addStruct(
"thermal_solid",
"Thermal solid module");
68 if (!inlet.verify()) {
69 SLIC_ERROR_ROOT(
"Input file failed to verify.");
90 int dim,
int order, std::optional<serac::SolidMechanicsInputOptions> solid_mechanics_options,
91 std::optional<serac::HeatTransferInputOptions> heat_transfer_options,
92 std::optional<serac::ThermomechanicsInputOptions> thermomechanics_options, std::string mesh_tag,
int cycle,
95 std::unique_ptr<serac::BasePhysics> main_physics;
96 if (thermomechanics_options) {
100 std::make_unique<serac::Thermomechanics<1, 2>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
101 }
else if (dim == 3) {
103 std::make_unique<serac::Thermomechanics<1, 3>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
105 }
else if (order == 2) {
108 std::make_unique<serac::Thermomechanics<2, 2>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
109 }
else if (dim == 3) {
111 std::make_unique<serac::Thermomechanics<2, 3>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
113 }
else if (order == 3) {
116 std::make_unique<serac::Thermomechanics<3, 2>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
117 }
else if (dim == 3) {
119 std::make_unique<serac::Thermomechanics<3, 3>>(*thermomechanics_options,
"serac", mesh_tag, cycle, t);
122 }
else if (solid_mechanics_options && heat_transfer_options) {
125 main_physics = std::make_unique<serac::Thermomechanics<1, 2>>(*heat_transfer_options, *solid_mechanics_options,
126 "serac", mesh_tag, cycle, t);
127 }
else if (dim == 3) {
128 main_physics = std::make_unique<serac::Thermomechanics<1, 3>>(*heat_transfer_options, *solid_mechanics_options,
129 "serac", mesh_tag, cycle, t);
131 }
else if (order == 2) {
133 main_physics = std::make_unique<serac::Thermomechanics<2, 2>>(*heat_transfer_options, *solid_mechanics_options,
134 "serac", mesh_tag, cycle, t);
135 }
else if (dim == 3) {
136 main_physics = std::make_unique<serac::Thermomechanics<2, 3>>(*heat_transfer_options, *solid_mechanics_options,
137 "serac", mesh_tag, cycle, t);
139 }
else if (order == 3) {
141 main_physics = std::make_unique<serac::Thermomechanics<3, 2>>(*heat_transfer_options, *solid_mechanics_options,
142 "serac", mesh_tag, cycle, t);
143 }
else if (dim == 3) {
144 main_physics = std::make_unique<serac::Thermomechanics<3, 3>>(*heat_transfer_options, *solid_mechanics_options,
145 "serac", mesh_tag, cycle, t);
148 }
else if (solid_mechanics_options) {
152 std::make_unique<serac::SolidMechanics<1, 2>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
153 }
else if (dim == 3) {
155 std::make_unique<serac::SolidMechanics<1, 3>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
157 }
else if (order == 2) {
160 std::make_unique<serac::SolidMechanics<2, 2>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
161 }
else if (dim == 3) {
163 std::make_unique<serac::SolidMechanics<2, 3>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
165 }
else if (order == 3) {
168 std::make_unique<serac::SolidMechanics<3, 2>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
169 }
else if (dim == 3) {
171 std::make_unique<serac::SolidMechanics<3, 3>>(*solid_mechanics_options,
"serac", mesh_tag, cycle, t);
174 }
else if (heat_transfer_options) {
177 main_physics = std::make_unique<serac::HeatTransfer<1, 2>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
178 }
else if (dim == 3) {
179 main_physics = std::make_unique<serac::HeatTransfer<1, 3>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
181 }
else if (order == 2) {
183 main_physics = std::make_unique<serac::HeatTransfer<2, 2>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
184 }
else if (dim == 3) {
185 main_physics = std::make_unique<serac::HeatTransfer<2, 3>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
187 }
else if (order == 3) {
189 main_physics = std::make_unique<serac::HeatTransfer<3, 2>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
190 }
else if (dim == 3) {
191 main_physics = std::make_unique<serac::HeatTransfer<3, 3>>(*heat_transfer_options,
"serac", mesh_tag, cycle, t);
195 SLIC_ERROR_ROOT(
"Neither solid, heat_transfer, nor thermal_solid blocks specified in the input file.");
209 int getOrder(std::optional<serac::SolidMechanicsInputOptions> solid_mechanics_options,
210 std::optional<serac::HeatTransferInputOptions> heat_transfer_options,
211 std::optional<serac::ThermomechanicsInputOptions> thermomechanics_options)
214 if (thermomechanics_options) {
215 order = thermomechanics_options->solid_options.order;
216 int thermal_order = thermomechanics_options->thermal_options.order;
218 order != thermal_order,
219 axom::fmt::format(
"Solid order '{0}' and thermal order '{1}'' do not match.", order, thermal_order));
220 }
else if (solid_mechanics_options && heat_transfer_options) {
221 order = solid_mechanics_options->order;
222 int thermal_order = heat_transfer_options->order;
224 order != thermal_order,
225 axom::fmt::format(
"Solid order '{0}' and thermal order '{1}'' do not match.", order, thermal_order));
226 }
else if (solid_mechanics_options) {
227 order = solid_mechanics_options->order;
228 }
else if (heat_transfer_options) {
229 order = heat_transfer_options->order;
231 SLIC_ERROR_ROOT(
"Neither solid, heat_transfer, nor thermal_solid blocks specified in the input file.");
233 SLIC_ERROR_ROOT_IF(order < 1 || order > 3,
234 axom::fmt::format(
"Invalid solver order '{0}' given. Valid values are 1, 2, or 3.", order));
246 int main(
int argc,
char* argv[])
251 const std::string warning_message = R
"PREFIX(******************************
252 This Serac driver does not
253 currently work due to missing
254 input file functionality.
255 ******************************)PREFIX";
256 SLIC_INFO(warning_message);
259 std::unordered_map<std::string, std::string> cli_opts =
264 bool print_version = cli_opts.find(
"version") != cli_opts.end();
275 std::string input_file_path =
"";
276 auto search = cli_opts.find(
"input-file");
277 if (search != cli_opts.end()) {
278 input_file_path = search->second;
287 std::string output_directory =
"";
288 search = cli_opts.find(
"output-directory");
289 if (search != cli_opts.end()) {
290 output_directory = search->second;
292 axom::utilities::filesystem::makeDirsForPath(output_directory);
294 search = cli_opts.find(
"paraview-directory");
296 std::optional<std::string> paraview_output_dir = {};
297 if (search != cli_opts.end()) {
298 paraview_output_dir = search->second;
299 axom::utilities::filesystem::makeDirsForPath(*paraview_output_dir);
303 std::optional<int> restart_cycle;
304 if (
auto cycle = cli_opts.find(
"restart-cycle"); cycle != cli_opts.end()) {
305 restart_cycle = std::stoi(cycle->second);
309 axom::sidre::DataStore datastore;
319 bool create_input_file_docs = cli_opts.find(
"create-input-file-docs") != cli_opts.end();
320 if (create_input_file_docs) {
321 std::string input_docs_path = axom::utilities::filesystem::joinPath(output_directory,
"serac_input.rst");
322 inlet.write(axom::inlet::SphinxWriter(input_docs_path));
327 if (cli_opts.find(
"print-unused") != cli_opts.end()) {
328 const std::vector<std::string> all_unexpected_names = inlet.unexpectedNames();
329 if (all_unexpected_names.size() != 0) {
330 SLIC_INFO(
"Printing unused entries in input file:");
331 for (
auto& x : all_unexpected_names) {
335 SLIC_INFO(
"No unused entries in input file.");
341 std::string input_values_path = axom::utilities::filesystem::joinPath(output_directory,
"serac_input_values.json");
342 datastore.getRoot()->getGroup(
"input_file")->save(input_values_path,
"json");
346 double t_final = inlet[
"t_final"];
347 double dt = inlet[
"dt"];
350 std::string mesh_tag{
"mesh}"};
353 if (!restart_cycle) {
356 if (
const auto file_opts = std::get_if<serac::mesh::FileInputOptions>(&mesh_options.extra_options)) {
357 file_opts->absolute_mesh_file_name =
365 cycle = *restart_cycle;
369 std::optional<serac::SolidMechanicsInputOptions> solid_mechanics_options;
370 std::optional<serac::HeatTransferInputOptions> heat_transfer_options;
371 std::optional<serac::ThermomechanicsInputOptions> thermomechanics_options;
374 if (inlet.isUserProvided(
"solid")) {
377 if (inlet.isUserProvided(
"heat_transfer")) {
380 if (inlet.isUserProvided(
"thermal_solid")) {
386 SLIC_ERROR_ROOT_IF(dim < 2 || dim > 3,
387 axom::fmt::format(
"Invalid mesh dimension '{0}' provided. Valid values are 2 or 3.", dim));
388 int order =
getOrder(solid_mechanics_options, heat_transfer_options, thermomechanics_options);
391 auto main_physics =
createPhysics(dim, order, solid_mechanics_options, heat_transfer_options, thermomechanics_options,
395 main_physics->completeSetup();
397 main_physics->initializeSummary(datastore, t_final, dt);
400 bool last_step =
false;
403 serac::logger::flush();
406 double dt_real =
std::min(dt, t_final - t);
412 SLIC_INFO_ROOT(
"step " << cycle <<
", t = " << t);
415 main_physics->advanceTimestep(dt_real);
418 main_physics->outputStateToDisk(paraview_output_dir);
421 main_physics->saveSummary(datastore, t);
424 last_step = (t >= t_final - 1e-8 * dt);
This file contains the interface used for retrieving information about how the driver is configured.
static void initialize(axom::sidre::DataStore &ds, const std::string &output_directory)
Initializes the StateManager with a sidre DataStore (into which state will be written/read)
static double load(const int cycle_to_load, const std::string &mesh_tag)
Loads an existing DataCollection.
static mfem::ParMesh & mesh(const std::string &mesh_tag)
Returns a non-owning reference to mesh held by StateManager.
static mfem::ParMesh & setMesh(std::unique_ptr< mfem::ParMesh > pmesh, const std::string &mesh_tag)
Gives ownership of mesh to StateManager.
This file contains the all the necessary functions and macros required for interacting with the comma...
This file contains the declaration of an equation solver wrapper.
An object containing the solver for a heat transfer PDE.
A function intended to be used as part of a driver to initialize common libraries.
This file contains the all the necessary functions and macros required for logging as well as a helpe...
This file contains helper functions for importing and managing various mesh objects.
std::unordered_map< std::string, std::string > defineAndParse(int argc, char *argv[], std::string app_description)
Defines command line options and parses the found values.
void printGiven(std::unordered_map< std::string, std::string > &cli_opts)
Prints all given command line options to the screen.
std::unique_ptr< mfem::ParMesh > buildParallelMesh(const InputOptions &options, const MPI_Comm comm)
Constructs an MFEM parallel mesh from a set of input options.
void outputSummary(const axom::sidre::DataStore &datastore, const std::string &output_directory, const FileFormat file_format)
Outputs simulation summary data from the datastore to the given file only on rank 0.
Accelerator functionality.
void exitGracefully(bool error)
Exits the program gracefully after cleaning up necessary tasks.
SERAC_HOST_DEVICE auto min(dual< gradient_type > a, double b)
Implementation of min for dual numbers.
std::pair< int, int > initialize(int argc, char *argv[], MPI_Comm comm)
Initializes MPI, signal handling, and logging.
std::string about()
Returns a string about the configuration of Serac.
void defineInputFileSchema(axom::inlet::Inlet &inlet)
Define the input file structure for the driver code.
void printRunInfo()
Outputs basic run information to the screen.
This file contains the all the necessary functions for outputting simulation data.
int main(int argc, char *argv[])
The main serac driver code.
int getOrder(std::optional< serac::SolidMechanicsInputOptions > solid_mechanics_options, std::optional< serac::HeatTransferInputOptions > heat_transfer_options, std::optional< serac::ThermomechanicsInputOptions > thermomechanics_options)
Return and check correctness of the order of discretization.
std::unique_ptr< serac::BasePhysics > createPhysics(int dim, int order, std::optional< serac::SolidMechanicsInputOptions > solid_mechanics_options, std::optional< serac::HeatTransferInputOptions > heat_transfer_options, std::optional< serac::ThermomechanicsInputOptions > thermomechanics_options, std::string mesh_tag, int cycle, double t)
Constructs the appropriate physics object using the input file options.
An object containing the solver for total Lagrangian finite deformation solid mechanics.
This file contains the declaration of the StateManager class.
Helper functions for exiting Serac cleanly.
An object containing an operator-split thermal structural solver.