Line data Source code
1 : // SPDX-FileCopyrightText: 2024 Daniel Abele <daniel.abele@dlr.de>
2 : //
3 : // SPDX-License-Identifier: BSD-3-Clause
4 :
5 : #include "issm-precice/confreader.hpp"
6 : #include "issm-precice/logging.hpp"
7 : #include "shared/Enum/Enum.h"
8 : #include "yaml-cpp/yaml.h"
9 : #include "boost/algorithm/string/predicate.hpp"
10 : #include <fstream>
11 : #include <iostream>
12 :
13 : namespace ipc
14 : {
15 :
16 : template<class T>
17 18 : T get_or_default(const YAML::Node& yaml, const char* name, T def)
18 : {
19 36 : if (auto el = yaml[name]; yaml[name].IsDefined())
20 : {
21 5 : return el.as<T>();
22 : }
23 : else
24 : {
25 13 : return def;
26 : }
27 : }
28 :
29 2 : IssmConfig issm_config(const YAML::Node& yaml)
30 : {
31 2 : IssmConfig issm;
32 2 : issm.root_path = yaml["root_path"].as<std::string>();
33 2 : issm.model_name = yaml["model_name"].as<std::string>();
34 2 : issm.output_frequency = get_or_default(yaml, "output_frequency", -1);
35 2 : issm.time_step = get_or_default(yaml, "time_step", -1.0);
36 2 : return issm;
37 0 : }
38 :
39 2 : Config read_config(const std::filesystem::path& file, MPI_Comm comm)
40 : {
41 2 : IPC_LOG_INFO_0(comm, "Reading config file {}", file.string());
42 :
43 2 : Config config;
44 :
45 2 : auto adapter_options = YAML::LoadFile(file);
46 :
47 : // precice options
48 2 : config.precice.config_file = adapter_options["precice_config_file_name"].as<std::string>();
49 2 : config.precice.solver_name = adapter_options["participant_name"].as<std::string>();
50 :
51 : // issm
52 2 : config.issm = issm_config(adapter_options["issm"]);
53 :
54 : // mesh
55 2 : if (adapter_options["interfaces"].size() != 1)
56 : {
57 0 : throw std::runtime_error("Must define exactly one coupling interface.");
58 : }
59 2 : auto interface_options = adapter_options["interfaces"][0];
60 2 : config.mesh.name = interface_options["mesh_name"].as<std::string>();
61 2 : if (interface_options["patches"].size() != 1)
62 : {
63 0 : throw std::runtime_error("Must have exactly one patch per coupling interface.");
64 : }
65 2 : auto patch = interface_options["patches"][0].as<std::string>();
66 2 : if (boost::iequals(patch, "Base"))
67 : {
68 1 : config.mesh.type = Mesh2dConfig{.layer = 0};
69 : }
70 1 : else if (boost::iequals(patch, "Surface"))
71 : {
72 1 : config.mesh.type = Mesh2dConfig{.layer = -1};
73 : }
74 : else
75 : {
76 0 : throw std::runtime_error("Invalid patch. Must be one of [ base, surface ]");
77 : }
78 :
79 2 : auto&& write_data = interface_options["write_data"];
80 6 : for (auto&& e : write_data)
81 : {
82 4 : auto entry = VariableDefinition{
83 8 : .id = definitions(StringToEnumx(e["solver_name"].as<std::string>().c_str())),
84 : .direction = DataDirection::Write,
85 : .data_name = e["name"].as<std::string>(),
86 : .flags = (VariableFlags::None |
87 16 : (boost::icontains(get_or_default(e, "operation", std::string("")), "DepthAverage")
88 : ? VariableFlags::DepthAverage
89 : : VariableFlags::None) |
90 12 : (boost::icontains(get_or_default(e, "operation", std::string("")), "Initialize")
91 : ? VariableFlags::Initialize
92 8 : : VariableFlags::None)),
93 12 : };
94 4 : config.variables.push_back(entry);
95 6 : }
96 2 : auto&& read_data = interface_options["read_data"];
97 5 : for (auto&& e : read_data)
98 : {
99 3 : auto entry = VariableDefinition{
100 6 : .id = definitions(StringToEnumx(e["solver_name"].as<std::string>().c_str())),
101 : .direction = DataDirection::Read,
102 : .data_name = e["name"].as<std::string>(),
103 : .flags = VariableFlags::None |
104 12 : (boost::icontains(get_or_default(e, "operation", std::string("")), "Extrude")
105 : ? VariableFlags::Extrude
106 : : VariableFlags::None) |
107 9 : (boost::icontains(get_or_default(e, "constraint", std::string("")), "Constraint")
108 : ? VariableFlags::Constraint
109 6 : : VariableFlags::None),
110 9 : };
111 3 : config.variables.push_back(entry);
112 5 : }
113 :
114 4 : return config;
115 2 : }
116 :
117 : } // namespace ipc
|