Line data Source code
1 : // SPDX-FileCopyrightText: 2024 Daniel Abele <daniel.abele@dlr.de> 2 : // 3 : // SPDX-License-Identifier: BSD-3-Clause 4 : 5 : #pragma once 6 : 7 : #include "issm-precice/confreader.hpp" 8 : #include "issm-precice/mesh.hpp" 9 : #include "mpi.h" 10 : #include <filesystem> 11 : #include <memory> 12 : #include <ranges> 13 : #include <string> 14 : #include <vector> 15 : #include <span> 16 : 17 : class FemModel; 18 : 19 : namespace ipc 20 : { 21 : 22 : struct NoopDeleter 23 : { 24 40 : void operator()(FemModel*) { } 25 : }; 26 : 27 : /** 28 : * Unique ptr to own an ISSM FemModel object. 29 : * Deleter does not do anything because FemModel causes a segfault on deletion. 30 : */ 31 : using FemModelPtr = std::unique_ptr<FemModel, NoopDeleter>; 32 : 33 : /** 34 : * Create an ISSM FemModel by loading the specified model. 35 : * @param root_path Directory where the model files are stored. 36 : * @param model_name Name of the model to load. 37 : * @param comm MPI communicator to use by ISSM. 38 : */ 39 : FemModelPtr make_fem_model(const std::filesystem::path& root_path, const std::string& model_name, MPI_Comm comm); 40 : 41 : /** 42 : * Get the ISSM input id of the given name. 43 : */ 44 : definitions issm_input_id(const std::string& input_name); 45 : 46 : /** 47 : * Get the name of the ISSM input. 48 : */ 49 : const char* issm_input_name(definitions input_id); 50 : 51 : /** 52 : * Get the ISSM input that stores depth averaged values for the specified input. 53 : */ 54 : definitions depth_average_input(definitions input_id); 55 : 56 : /** 57 : * Abstract interface for ISSM used for coupling. 58 : */ 59 : class IIssm 60 : { 61 : public: 62 : /** 63 : * Virtual destructor. 64 : */ 65 : virtual ~IIssm(); 66 : 67 : /** 68 : * Get the vertices of the coupled interface mesh. 69 : * @param with_connectivity True if mesh connectivity is required. 70 : * Warning: mesh connectivity also implies ghost vertices in distributed meshes, this breaks RBF mapping methods. 71 : * @returns Vertices of the ISSM mesh and the elements they belong to. 72 : */ 73 : virtual Mesh get_vertices(bool with_connectivity) const = 0; 74 : 75 : /** 76 : * Maximum length of next time step allowed by the model (e.g. for numeric stability). 77 : */ 78 : virtual double get_max_time_step() const = 0; 79 : 80 : /** 81 : * Set the specified input for the vertices. 82 : * @param input Input to set. 83 : * @param vertices Vertices and corresponding Element to set the values for. 84 : * @param values Values to set. 85 : */ 86 : virtual void 87 : set_input(definitions input, const std::vector<Vertex>& vertices, std::span<const double> values) = 0; 88 : 89 : /** 90 : * Set the specified constraints for the vertices. 91 : * @param input Input to set. 92 : * @param vertices Vertices and corresponding Element to set the values for. 93 : * @param values Values to set. 94 : */ 95 : virtual void 96 : set_constraints(definitions input, const std::vector<Vertex>& vertices, std::span<const double> values) = 0; 97 : 98 : /** 99 : * Extrude the specified input. 100 : * Values of the input are copied from base (or surface, depending on the used coupling interface) 101 : * to the other layers of a 3D ISSM model. No effect on 2D ISSM models. 102 : * @param input Input to extrude. 103 : * @param vertices Vertices to extrude. 104 : */ 105 : virtual void extrude(definitions input, const std::vector<Vertex>& vertices) = 0; 106 : 107 : /** 108 : * Compute valid initial values for the input. 109 : * For most inputs, this does nothing since the input has valid values in 110 : * the ISSM model setup. Some inputs are not required to be have correct initial values as they are 111 : * computed by ISSM without initial state. For these inputs, this function does the necessary computation that 112 : * would normally happen only during the simulation. 113 : * @param input Input to initialize. 114 : */ 115 : virtual void initialize(definitions input) = 0; 116 : 117 : /** 118 : * Get the specified input for the vertices. 119 : * @param input Input to get. 120 : * @param vertices Vertices and corresponding Element to get the values for. 121 : * @param[out] values Vector to store the values in. Will be overwritten by the function. 122 : */ 123 : virtual void 124 : get_input(definitions input, const std::vector<Vertex>& vertices, std::span<double> values) const = 0; 125 : 126 : /** 127 : * Run depth averaging for the specified input. 128 : * Computes the average of an input over all the layers of a 3D ISSM model and stores it 129 : * in a specific input that depends on the argument input. For every supported input there is one 130 : * corresponding average input. 131 : * @param input Input to depth average. 132 : * @param vertices vertices to depth average. 133 : * @returns Input where the depth averaged values are stored. 134 : */ 135 : virtual definitions depth_average(definitions input, const std::vector<Vertex>& vertices) = 0; 136 : 137 : /** 138 : * Advance the simulation one time step. 139 : * @param dt Length of the time step. 140 : */ 141 : virtual void solve(double dt) = 0; 142 : }; 143 : 144 : /** 145 : * Concretization of the IIssm interface. 146 : * Gives access to ISSM model data required for coupling. 147 : */ 148 : class Issm : public IIssm 149 : { 150 : public: 151 : /** 152 : * Initialize ISSM by loading a model. 153 : * @param root_path Path to directory that stores the model. 154 : * @param model_name Name of the model. 155 : * @param mesh Definition of the coupling interface mesh. 156 : * @param comm MPI communicator to used by ISSM. 157 : */ 158 : Issm( 159 : const std::filesystem::path& root_path, 160 : const std::string& model_name, 161 : const MeshConfig& mesh, 162 : MPI_Comm comm); 163 : 164 : /** 165 : * @copydoc IIssm::get_vertices() 166 : */ 167 : Mesh get_vertices(bool with_connectivity) const override; 168 : 169 : /** 170 : * Like IIssm::get_vertices(), but for a dynamic coupling mesh instead of the initial one. 171 : * Mainly for testing. 172 : */ 173 : Mesh get_vertices(const MeshConfig& mesh, bool with_connectivity) const; 174 : 175 : /** 176 : * @copydoc IIssm::get_time_step() 177 : */ 178 : double get_max_time_step() const override; 179 : 180 : /** 181 : * @copydoc IIssm::initialize() 182 : */ 183 : void initialize(definitions input) override; 184 : 185 : /** 186 : * @copydoc IIssm:set_input() 187 : */ 188 : void set_input(definitions input, const std::vector<Vertex>& vertices, std::span<const double> values) override; 189 : 190 : /** 191 : * @copydoc IIssm:set_constraints() 192 : */ 193 : virtual void 194 : set_constraints(definitions input, const std::vector<Vertex>& vertices, std::span<const double> values) override; 195 : 196 : /** 197 : * @copydoc IIssm:extrude() 198 : */ 199 : void extrude(definitions input, const std::vector<Vertex>& vertices) override; 200 : 201 : /** 202 : * @copydoc IIssm:get_input() 203 : */ 204 : void get_input(definitions input, const std::vector<Vertex>& vertices, std::span<double> values) const override; 205 : 206 : /** 207 : * @copydoc IIssm:depth_average() 208 : */ 209 : definitions depth_average(definitions input, const std::vector<Vertex>& vertices) override; 210 : 211 : /** 212 : * @copydoc IIssm:solve() 213 : */ 214 : void solve(double dt) override; 215 : 216 : void set_time_step_override(double dt); 217 : void set_output_frequency_override(int f); 218 : 219 : private: 220 : bool try_set_constraint_value(const Vertex&, definitions input, double value) const; 221 : std::vector<double> synchronize_ghosts(const std::vector<Vertex>& vertices, std::span<const double> values) const; 222 : 223 : private: 224 : FemModelPtr m_model; 225 : MeshConfig m_coupling_mesh_config; 226 : Mesh m_connected_mesh; //includes ghost vertices and edges (e.g. for Lin. Cell Interp. mapping) 227 : Mesh m_unique_mesh; //omits ghost vertices and edges (e.g. for RBF mapping) 228 : double m_max_dt; 229 : bool m_initialized_stress_balance; 230 : double m_dt_override = -1.0; 231 : int m_output_frequency_override = -1; 232 : }; 233 : } // namespace ipc