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 12 : T get_or_default(const YAML::Node& yaml, const char* name, T def) 18 : { 19 24 : if (auto el = yaml[name]; yaml[name].IsDefined()) 20 : { 21 3 : return el.as<T>(); 22 : } 23 : else 24 : { 25 9 : return def; 26 : } 27 : } 28 : 29 1 : IssmConfig issm_config(const YAML::Node& yaml) 30 : { 31 1 : IssmConfig issm; 32 1 : issm.root_path = yaml["root_path"].as<std::string>(); 33 1 : issm.model_name = yaml["model_name"].as<std::string>(); 34 1 : issm.output_frequency = get_or_default(yaml, "output_frequency", -1); 35 1 : issm.time_step = get_or_default(yaml, "time_step", -1.0); 36 1 : return issm; 37 0 : } 38 : 39 1 : Config read_config(const std::filesystem::path& file, MPI_Comm comm) 40 : { 41 1 : IPC_LOG_INFO_0(comm, "Reading config file {}", file.string()); 42 : 43 1 : Config config; 44 : 45 1 : auto adapter_options = YAML::LoadFile(file); 46 : 47 : // precice options 48 1 : config.precice.config_file = adapter_options["precice_config_file_name"].as<std::string>(); 49 1 : config.precice.solver_name = adapter_options["participant_name"].as<std::string>(); 50 : 51 : // issm 52 1 : config.issm = issm_config(adapter_options["issm"]); 53 : 54 : // mesh 55 1 : if (adapter_options["interfaces"].size() != 1) 56 : { 57 0 : throw std::runtime_error("Must define exactly one coupling interface."); 58 : } 59 1 : auto interface_options = adapter_options["interfaces"][0]; 60 1 : config.mesh.name = interface_options["mesh_name"].as<std::string>(); 61 1 : 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 1 : if (boost::iequals(patch, "Base")) 67 : { 68 1 : config.mesh.type = Mesh2dDefinition{.layer = 0}; 69 : } 70 0 : else if (boost::iequals(patch, "Surface")) 71 : { 72 0 : config.mesh.type = Mesh2dDefinition{.layer = -1}; 73 : } 74 : else 75 : { 76 0 : throw std::runtime_error("Invalid patch. Must be one of [ base, surface ]"); 77 : } 78 : 79 1 : auto&& write_data = interface_options["write_data"]; 80 4 : for (auto&& e : write_data) 81 : { 82 3 : auto entry = VariableDefinition{ 83 6 : .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 6 : (boost::icontains(get_or_default(e, "operation", std::string("")), "DepthAverage") 88 : ? VariableFlags::DepthAverage 89 : : VariableFlags::None) | 90 6 : (boost::icontains(get_or_default(e, "operation", std::string("")), "Initialize") 91 : ? VariableFlags::Initialize 92 6 : : VariableFlags::None)), 93 6 : }; 94 3 : config.variables.push_back(entry); 95 4 : } 96 1 : auto&& read_data = interface_options["read_data"]; 97 3 : for (auto&& e : read_data) 98 : { 99 2 : auto entry = VariableDefinition{ 100 4 : .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 4 : (boost::icontains(get_or_default(e, "operation", std::string("")), "Extrude") 105 : ? VariableFlags::Extrude 106 : : VariableFlags::None) | 107 4 : (boost::icontains(get_or_default(e, "constraint", std::string("")), "Constraint") 108 : ? VariableFlags::Constraint 109 4 : : VariableFlags::None), 110 4 : }; 111 2 : config.variables.push_back(entry); 112 3 : } 113 : 114 2 : return config; 115 1 : } 116 : 117 : } // namespace ipc