12 #include <boost/program_options.hpp>
13 #include <boost/property_tree/info_parser.hpp>
14 #include <boost/property_tree/json_parser.hpp>
16 #include <Kokkos_Core.hpp>
21 #ifdef ADAMANTINE_WITH_ADIAK
25 #ifdef ADAMANTINE_WITH_CALIPER
26 #include <caliper/cali-manager.h>
30 #define RUN_ENSEMBLE_SOLID_HOST_IF(z, SEQ) \
31 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
32 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
33 BOOST_PP_SEQ_ELEM(2, SEQ), \
34 BOOST_PP_SEQ_ELEM(3, SEQ))) \
35 run_ensemble<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
36 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::Solid, \
37 dealii::MemorySpace::Host>(communicator, database, timers);
39 #define RUN_ENSEMBLE_SOLID_HOST(TUPLE) \
40 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
41 RUN_ENSEMBLE_SOLID_HOST_IF, \
42 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
44 #define RUN_ENSEMBLE_SOLID_LIQUID_HOST_IF(z, SEQ) \
45 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
46 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
47 BOOST_PP_SEQ_ELEM(2, SEQ), \
48 BOOST_PP_SEQ_ELEM(3, SEQ))) \
49 run_ensemble<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
50 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquid, \
51 dealii::MemorySpace::Host>(communicator, database, timers);
53 #define RUN_ENSEMBLE_SOLID_LIQUID_HOST(TUPLE) \
54 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
55 RUN_ENSEMBLE_SOLID_LIQUID_HOST_IF, \
56 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
58 #define RUN_ENSEMBLE_SOLID_LIQUID_POWDER_HOST_IF(z, SEQ) \
59 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
60 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
61 BOOST_PP_SEQ_ELEM(2, SEQ), \
62 BOOST_PP_SEQ_ELEM(3, SEQ))) \
63 run_ensemble<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
64 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquidPowder, \
65 dealii::MemorySpace::Host>(communicator, database, timers);
67 #define RUN_ENSEMBLE_SOLID_LIQUID_POWDER_HOST(TUPLE) \
68 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
69 RUN_ENSEMBLE_SOLID_LIQUID_POWDER_HOST_IF, \
70 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
72 #define RUN_SOLID_HOST_IF(z, SEQ) \
73 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
74 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
75 BOOST_PP_SEQ_ELEM(2, SEQ), \
76 BOOST_PP_SEQ_ELEM(3, SEQ))) \
77 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
78 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::Solid, \
79 dealii::MemorySpace::Host>(communicator, database, timers);
81 #define RUN_SOLID_HOST(TUPLE) \
82 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
84 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
86 #define RUN_SOLID_LIQUID_HOST_IF(z, SEQ) \
87 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
88 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
89 BOOST_PP_SEQ_ELEM(2, SEQ), \
90 BOOST_PP_SEQ_ELEM(3, SEQ))) \
91 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
92 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquid, \
93 dealii::MemorySpace::Host>(communicator, database, timers);
95 #define RUN_SOLID_LIQUID_HOST(TUPLE) \
96 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
97 RUN_SOLID_LIQUID_HOST_IF, \
98 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
100 #define RUN_SOLID_LIQUID_POWDER_HOST_IF(z, SEQ) \
101 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
102 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
103 BOOST_PP_SEQ_ELEM(2, SEQ), \
104 BOOST_PP_SEQ_ELEM(3, SEQ))) \
105 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
106 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquidPowder, \
107 dealii::MemorySpace::Host>(communicator, database, timers);
109 #define RUN_SOLID_LIQUID_POWDER_HOST(TUPLE) \
110 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
111 RUN_SOLID_LIQUID_POWDER_HOST_IF, \
112 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
114 #define RUN_SOLID_DEV_IF(z, SEQ) \
115 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
116 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
117 BOOST_PP_SEQ_ELEM(2, SEQ), \
118 BOOST_PP_SEQ_ELEM(3, SEQ))) \
119 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
120 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::Solid, \
121 dealii::MemorySpace::Default>(communicator, database, timers);
123 #define RUN_SOLID_DEVICE(TUPLE) \
124 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
126 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
128 #define RUN_SOLID_LIQUID_DEV_IF(z, SEQ) \
129 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
130 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
131 BOOST_PP_SEQ_ELEM(2, SEQ), \
132 BOOST_PP_SEQ_ELEM(3, SEQ))) \
133 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
134 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquid, \
135 dealii::MemorySpace::Default>(communicator, database, timers);
137 #define RUN_SOLID_LIQUID_DEVICE(TUPLE) \
138 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
139 RUN_SOLID_LIQUID_DEV_IF, \
140 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
142 #define RUN_SOLID_LIQUID_POWDER_DEV_IF(z, SEQ) \
143 if (BOOST_PP_SEQ_ELEM(0, SEQ) == \
144 std::tuple<int, int, int>(BOOST_PP_SEQ_ELEM(1, SEQ), \
145 BOOST_PP_SEQ_ELEM(2, SEQ), \
146 BOOST_PP_SEQ_ELEM(3, SEQ))) \
147 run<BOOST_PP_SEQ_ELEM(1, SEQ), BOOST_PP_SEQ_ELEM(2, SEQ), \
148 BOOST_PP_SEQ_ELEM(3, SEQ), adamantine::SolidLiquidPowder, \
149 dealii::MemorySpace::Default>(communicator, database, timers);
151 #define RUN_SOLID_LIQUID_POWDER_DEVICE(TUPLE) \
152 BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
153 RUN_SOLID_LIQUID_POWDER_DEV_IF, \
154 ((TUPLE))(ADAMANTINE_DIM)(ADAMANTINE_N_MATERIALS)(ADAMANTINE_P_ORDER))
156 std::tuple<int, int, int>
165 unsigned int p_order = 0;
166 unsigned int n_material_states = 0;
168 bool use_table = database.get<std::string>(
"property_format") ==
"table";
171 unsigned int const n_materials = database.get<
unsigned int>(
"n_materials");
173 std::vector<dealii::types::material_id> material_ids;
174 for (dealii::types::material_id
id = 0;
175 id < dealii::numbers::invalid_material_id; ++id)
177 if (database.count(
"material_" + std::to_string(
id)) != 0)
178 material_ids.push_back(
id);
179 if (material_ids.size() == n_materials)
183 for (
auto const material_id : material_ids)
186 boost::property_tree::ptree
const &material_database =
187 database.get_child(
"material_" + std::to_string(material_id));
189 for (
unsigned int state = 0;
193 boost::optional<boost::property_tree::ptree const &> state_database =
194 material_database.get_child_optional(
202 boost::optional<std::string>
const property =
203 state_database.get().get_optional<std::string>(
209 n_material_states = std::max(state + 1, n_material_states);
213 std::string property_string =
property.get();
214 property_string.erase(std::remove_if(property_string.begin(),
215 property_string.end(),
217 { return std::isspace(x); }),
218 property_string.end());
219 std::vector<std::string> parsed_property;
220 boost::split(parsed_property, property_string,
221 [](
char c) {
return c ==
','; });
223 static_cast<unsigned int>(parsed_property.size() - 1),
235 "Error when computing the polynomial order of the material properties");
237 n_material_states > 0 && n_material_states < 4,
238 "Error when computing the number of material states");
240 return std::make_tuple(n_materials, p_order, n_material_states);
243 int main(
int argc,
char *argv[])
245 #ifdef ADAMANTINE_WITH_CALIPER
246 CALI_MARK_BEGIN(
"main");
249 dealii::Utilities::MPI::MPI_InitFinalize mpi_initialization(
250 argc, argv, dealii::numbers::invalid_unsigned_int);
251 MPI_Comm communicator = MPI_COMM_WORLD;
253 #ifdef ADAMANTINE_WITH_ADIAK
254 adiak_init(&communicator);
257 adiak::executablepath();
260 adiak::clustername();
264 std::vector<adamantine::Timer> timers;
267 bool profiling =
false;
270 namespace boost_po = boost::program_options;
274 boost_po::options_description description(
"Options:");
275 description.add_options()(
"help,h",
"Produce help message.")(
276 "input-file,i", boost_po::value<std::string>(),
277 "Name of the input file.")(
278 "output-dir,o", boost_po::value<std::string>(),
279 "Output directory; defaults to the current working directory.");
283 boost_po::variables_map map;
284 auto parsed_line = boost_po::command_line_parser(argc, argv)
285 .options(description)
286 .allow_unregistered()
288 boost_po::store(parsed_line, map);
289 boost_po::notify(map);
291 if (map.count(
"help") == 1)
293 std::cout << description << std::endl;
298 std::vector<std::string> unrecognized_options =
299 boost_po::collect_unrecognized(parsed_line.options,
300 boost_po::include_positional);
301 for (
auto const &options : unrecognized_options)
303 if (options ==
"--kokkos-help")
310 std::string
const filename = map[
"input-file"].as<std::string>();
312 boost::property_tree::ptree database;
313 if (std::filesystem::path(filename).extension().native() ==
".json")
315 boost::property_tree::json_parser::read_json(filename, database);
319 boost::property_tree::info_parser::read_info(filename, database);
325 catch (std::runtime_error
const &exception)
327 std::cerr << exception.what() << std::endl;
332 if (map.count(
"output-dir") == 1)
337 std::filesystem::absolute(map[
"output-dir"].as<std::string>())
339 std::filesystem::path::preferred_separator;
340 std::filesystem::create_directories(outdir);
342 database.put(
"post_processor.output_dir", outdir);
344 catch (std::runtime_error
const &exception)
346 std::cerr << exception.what() << std::endl;
353 std::filesystem::current_path(
354 std::filesystem::absolute(filename).parent_path());
356 #ifdef ADAMANTINE_WITH_CALIPER
357 cali::ConfigManager caliper_manager;
359 boost::optional<boost::property_tree::ptree &> profiling_optional_database =
360 database.get_child_optional(
"profiling");
361 if (profiling_optional_database)
363 auto profiling_database = profiling_optional_database.get();
365 if (profiling_database.get(
"timer",
false))
367 #ifdef ADAMANTINE_WITH_CALIPER
369 auto caliper_optional_string =
370 profiling_database.get_optional<std::string>(
"caliper");
371 if (caliper_optional_string)
372 caliper_manager.add(caliper_optional_string.get().c_str());
375 #ifdef ADAMANTINE_WITH_CALIPER
376 caliper_manager.start();
379 boost::optional<boost::property_tree::ptree &> ensemble_optional_database =
380 database.get_child_optional(
"ensemble");
381 bool ensemble_calc =
false;
382 if (ensemble_optional_database)
384 auto ensemble_database = ensemble_optional_database.get();
386 ensemble_calc = ensemble_database.get<
bool>(
"ensemble_simulation",
false);
389 boost::property_tree::ptree geometry_database =
390 database.get_child(
"geometry");
392 int const dim = geometry_database.get<
int>(
"dim");
395 auto const [n_materials, p_order, n_material_states] =
398 "Material properties have too many coefficients.");
400 unsigned int rank = dealii::Utilities::MPI::this_mpi_process(communicator);
403 std::string memory_space =
404 database.get<std::string>(
"memory_space",
"host");
406 #ifdef ADAMANTINE_WITH_ADIAK
407 if (memory_space ==
"device")
408 adiak::value(
"MemorySpace",
"Device");
410 adiak::value(
"MemorySpace",
"Host");
413 std::tuple<int, int, int> template_parameters(dim, n_materials, p_order);
417 if (memory_space ==
"device")
422 "Device version of ensemble simulations not yet implemented.");
426 std::cout <<
"Starting ensemble simulation" << std::endl;
428 if (n_material_states == 1)
432 else if (n_material_states == 2)
444 std::cout <<
"Starting non-ensemble simulation" << std::endl;
446 if (memory_space ==
"device")
448 if (n_material_states == 1)
452 else if (n_material_states == 2)
463 if (n_material_states == 1)
467 else if (n_material_states == 2)
479 std::cout <<
"Simulation done" << std::endl;
481 #ifdef ADAMANTINE_WITH_CALIPER
482 CALI_MARK_END(
"main");
483 caliper_manager.flush();
486 catch (boost::bad_any_cast &exception)
488 std::cerr << std::endl;
489 std::cerr <<
"Aborting." << std::endl;
490 std::cerr <<
"Error: " << exception.what() << std::endl << std::endl;
491 std::cerr <<
"There is a problem with the input file." << std::endl;
492 std::cerr <<
"Make sure that the input file is correct" << std::endl;
493 std::cerr <<
"and that you are using the following command" << std::endl;
494 std::cerr <<
"to run adamantine:" << std::endl;
495 std::cerr <<
"./adamantine --input-file=my_input_file" << std::endl;
496 std::cerr << std::endl;
498 catch (std::exception &exception)
500 std::cerr << std::endl;
501 std::cerr <<
"Aborting." << std::endl;
502 std::cerr <<
"Error: " << exception.what() << std::endl;
503 std::cerr << std::endl;
509 std::cerr << std::endl;
510 std::cerr <<
"Aborting." << std::endl;
511 std::cerr <<
"No error message." << std::endl;
512 std::cerr << std::endl;
518 if (profiling ==
true)
519 for (
auto &timer : timers)
522 #ifdef ADAMANTINE_WITH_ADIAK
int main(int argc, char *argv[])
#define RUN_ENSEMBLE_SOLID_HOST(TUPLE)
#define RUN_SOLID_LIQUID_DEVICE(TUPLE)
std::tuple< int, int, int > get_material_template_parameters(boost::property_tree::ptree &database)
#define RUN_ENSEMBLE_SOLID_LIQUID_POWDER_HOST(TUPLE)
#define RUN_SOLID_DEVICE(TUPLE)
#define RUN_SOLID_LIQUID_POWDER_DEVICE(TUPLE)
#define RUN_ENSEMBLE_SOLID_LIQUID_HOST(TUPLE)
void initialize_timers(MPI_Comm const &communicator, std::vector< adamantine::Timer > &timers)
void validate_input_database(boost::property_tree::ptree &database)
static std::array< std::string, 3 > const material_state_names
void wait_for_file(std::string const &filename, std::string const &message)
void ASSERT_THROW(bool cond, std::string const &message)
static std::array< std::string, 15 > const state_property_names
static unsigned constexpr int g_n_state_properties
static unsigned constexpr int n_material_states