svZeroDSolver
Loading...
Searching...
No Matches
SimulationParameters.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the
2// University of California, and others. SPDX-License-Identifier: BSD-3-Clause
3/**
4 * @file SimulationParameters.h
5 * @brief Source file to read simulation configuration
6 */
7#ifndef SVZERODSOLVER_SIMULATIONPARAMETERS_HPP_
8#define SVZERODSOLVER_SIMULATIONPARAMETERS_HPP_
9
10#include <list>
11#include <nlohmann/json.hpp>
12#include <stdexcept>
13#include <string>
14
15#include "ActivationFunction.h"
16#include "ActiveStress.h"
17#include "Model.h"
18#include "SphereMaterial.h"
19#include "State.h"
20#include "debug.h"
21
22/**
23 * @brief Simulation parameters
24 *
25 * Each of these can be set from the .json configuration file as part of the
26 * dict which is keyed by "simulation_parameters".
27 *
28 * For example:
29 *
30 * "simulation_parameters": {
31 * "number_of_cardiac_cycles": 30,
32 * "number_of_time_pts_per_cardiac_cycle": 201,
33 * "output_all_cycles": true
34 * }
35 *
36 * each parameter in the documentation may be specified using the attribute name
37 * and a value which takes the type of the attribute.
38 *
39 */
41 // Negative value indicates this has not
42 // been read from config file yet.
43 double sim_time_step_size{0.0}; ///< Simulation time step size
44 double sim_abs_tol{0.0}; ///< Absolute tolerance for simulation
45 double sim_cardiac_period{-1.0}; ///< Cardiac period
46 int sim_num_cycles{0}; ///< Number of cardiac cycles to simulate
47 int sim_pts_per_cycle{0}; ///< Number of time steps per cardiac cycle
49 false}; ///< If model does not have RCR boundary conditions, simulate
50 ///< model to convergence (based on cycle-to-cycle error of last
51 ///< two cardiac cycles); if it does, update number of cardiac
52 ///< cycles to simulate to be value estimated from equation 21 of
53 ///< Pfaller 2021
54 double sim_cycle_to_cycle_error{0}; ///< Cycle-to-cycle error
55 int sim_num_time_steps{0}; ///< Total number of time steps
56 int sim_nliter{0}; ///< Maximum number of non-linear iterations in time
57 ///< integration
58 double sim_rho_infty{0.0}; ///< Spectral radius of generalized-alpha
59 int output_interval{0}; ///< Interval of writing output
60
61 bool sim_steady_initial{0}; ///< Start from steady solution
63 false}; ///< Output variable based instead of vessel based
64 bool output_mean_only{false}; ///< Output only the mean value
65 bool output_derivative{false}; ///< Output derivatives
66 bool output_all_cycles{false}; ///< Output all cardiac cycles
67
69 false}; ///< Running 0D simulation coupled with external solver
70 double sim_external_step_size{0.0}; ///< Step size of external solver if
71 ///< running coupled
73 false}; ///< If true, warn instead of throwing when max nonlinear
74 ///< iterations is reached
75};
76
77/// @brief Wrapper class for nlohmann:json with error checking
78class JsonWrapper : public nlohmann::json {
79 public:
80 /**
81 * @brief Wrap around JSON configuration with detailed error message in case
82 * key is not found in configuration
83 *
84 * @param json JSON configuration
85 * @param component Name of the JSON sub-list to be extracted
86 * @param name_str Name string of the JSON sub-list to be extracted
87 * @param id Index of JSON sub-list to be extracted
88 */
89 JsonWrapper(const nlohmann::json& json, const std::string& component,
90 const std::string& name_str, const int& id)
91 : nlohmann::json(json[component][id]),
92 component(component),
93 name_str(name_str),
94 block_id(id) {}
95
96 /**
97 * @brief Wrap error check around key retrieval (throws detailed error if key
98 * doesn't exist)
99 *
100 * @param key Key to retrieve from JSON object
101 * @return JSON entry of key
102 */
103 const nlohmann::json& operator[](const char* key) const {
104 if (!this->contains(key)) {
105 if (this->contains(name_str)) {
106 const std::string name = this->at(name_str);
107 throw std::runtime_error("Key " + std::string(key) +
108 " not found in element " + name +
109 " of component " + component);
110 } else {
111 throw std::runtime_error(
112 "Key " + std::string(key) + " not found in element number " +
113 std::to_string(block_id) + " of component " + component);
114 }
115 }
116 return this->at(key);
117 }
118
119 // Inherit functions
120 using nlohmann::json::contains;
121 using nlohmann::json::value;
122 using nlohmann::json::operator[];
123
124 private:
125 std::string component;
126 std::string name_str;
127 int block_id;
128};
129
130/**
131 * @brief Generate a new block and add its parameters to the model
132 *
133 * @param model The model that the block is added to
134 * @param block_params_json The JSON configuration containing the block
135 * parameter values
136 * @param block_type The type of block
137 * @param name The name of the block
138 * @param internal Is this an internal block? This is relevant for the
139 * calibrator
140 * @param periodic Is this block periodic with the cardiac cycle? This is
141 * relevant for coupling with external solvers
142 * @return int The block count
143 */
144int generate_block(Model& model, const nlohmann::json& block_params_json,
145 const std::string& block_type, const std::string_view& name,
146 bool internal = false, bool periodic = true);
147
148/**
149 * @brief Create an activation function from JSON (analogous to generate_block)
150 *
151 * Validates keys against the activation type's params, reads scalar
152 * parameters, and returns a created ActivationFunction. Caller associates
153 * it with a chamber block via set_activation_function().
154 *
155 * @param model Model (for cardiac_cycle_period)
156 * @param j JSON object (e.g. chamber_config["activation_function"])
157 * @param chamber_name Chamber name for error messages
158 * @return Unique pointer to the created activation function
159 */
160std::unique_ptr<ActivationFunction> generate_activation_function(
161 Model& model, const nlohmann::json& j, const std::string& chamber_name);
162
163/**
164 * @brief Create a SphereMaterial from JSON (analogous to
165 * generate_activation_function)
166 *
167 * Validates keys against the material type's params, reads scalar parameters,
168 * and returns a created SphereMaterial. Caller associates it with a
169 * ChamberSphere block via set_material().
170 *
171 * @param j JSON object (e.g. chamber_config["material"])
172 * @param chamber_name Chamber name for error messages
173 * @return Unique pointer to the created material
174 */
175std::unique_ptr<SphereMaterial> generate_material(
176 const nlohmann::json& j, const std::string& chamber_name);
177
178/**
179 * @brief Create an ActiveStress model from JSON (analogous to
180 * generate_material)
181 *
182 * Validates keys against the active stress type's params, reads scalar
183 * parameters, and returns a created ActiveStress. Caller associates it with
184 * a ChamberSphere block via set_active_stress().
185 *
186 * @param j JSON object (e.g. chamber_config["active_stress"])
187 * @param chamber_name Chamber name for error messages
188 * @return Unique pointer to the created active stress model
189 */
190std::unique_ptr<ActiveStress> generate_active_stress(
191 const nlohmann::json& j, const std::string& chamber_name);
192
193/**
194 * @brief Load initial conditions from a JSON configuration
195 *
196 * @param config The JSON configuration
197 * @param model The model
198 * @return State Initial configuration for the model
199 */
200State load_initial_condition(const nlohmann::json& config, Model& model);
201
202/**
203 * @brief Load the simulation parameters from a JSON configuration
204 *
205 * @param config The JSON configuration
206 * @return SimulationParameters Simulation parameters read from configuration
207 */
208SimulationParameters load_simulation_params(const nlohmann::json& config);
209
210/**
211 * @brief Reconcile the cardiac cycle period between the model and parameters
212 *
213 * The period may be defined by a model block (e.g. a closed-loop block or a
214 * chamber) or by `simulation_parameters.cardiac_period`. This resolves
215 * `model.cardiac_cycle_period` from both sources, throws if the two disagree,
216 * and falls back to a default of 1.0 if neither defines it. Must be called by
217 * every entry point (solver and coupled interface) before blocks that depend
218 * on the period are used.
219 *
220 * @param model The 0D model
221 * @param params Simulation parameters read from the configuration
222 */
223void resolve_cardiac_cycle_period(Model& model,
224 const SimulationParameters& params);
225
226/**
227 * @brief Load the 0D block in the model from a configuration
228 *
229 * @param config The json configuration
230 * @param model The 0D model
231 * @
232 */
233void load_simulation_model(const nlohmann::json& config, Model& model);
234
235/**
236 * @brief Check that the JSON configuration has the required inputs
237 *
238 * @param config The JSON configuration
239 */
240void validate_input(const nlohmann::json& config);
241
242/**
243 * @brief Handle the creation of vessel blocks and connections with boundary
244 * conditions
245 *
246 * @param model The model the block is associated with
247 * @param connections Vector storing the connections between blocks
248 * @param config The JSON configuration
249 * @param component Name of the component to retrieve from config
250 * @param vessel_id_map Map between vessel names and IDs
251 */
252void create_vessels(
253 Model& model,
254 std::vector<std::tuple<std::string, std::string>>& connections,
255 const nlohmann::json& config, const std::string& component,
256 std::map<int, std::string>& vessel_id_map);
257
258/**
259 * @brief Handle the creation of external coupling blocks and connections with
260 * other blocks
261 *
262 * @param model The model the block is associated with
263 * @param connections Vector storing the connections between blocks
264 * @param config The JSON configuration
265 * @param component Name of the component to retrieve from config
266 * @param vessel_id_map Map between vessel names and IDs
267 * @param bc_type_map Map between boundary condition names and their types
268 */
269void create_external_coupling(
270 Model& model,
271 std::vector<std::tuple<std::string, std::string>>& connections,
272 const nlohmann::json& config, const std::string& component,
273 std::map<int, std::string>& vessel_id_map,
274 std::map<std::string, std::string>& bc_type_map);
275
276/**
277 * @brief Handle the creation of boundary condition blocks
278 *
279 * @param model The model the block is associated with
280 * @param config The JSON configuration
281 * @param component Name of the component to retrieve from config
282 * @param bc_type_map Map between boundary condition names and their types
283 * @param closed_loop_bcs List of boundary conditions that should be connected
284 * to a closed loop heart block
285 */
286void create_boundary_conditions(Model& model, const nlohmann::json& config,
287 const std::string& component,
288 std::map<std::string, std::string>& bc_type_map,
289 std::vector<std::string>& closed_loop_bcs);
290
291/**
292 * @brief Handle the creation of junctions and their connections
293 *
294 * @param model The model the block is associated with
295 * @param connections Vector storing the connections between blocks
296 * @param config The JSON configuration
297 * @param component Name of the component to retrieve from config
298 * @param vessel_id_map Map between vessel names and IDs
299 */
300void create_junctions(
301 Model& model,
302 std::vector<std::tuple<std::string, std::string>>& connections,
303 const nlohmann::json& config, const std::string& component,
304 std::map<int, std::string>& vessel_id_map);
305
306/**
307 * @brief Handle the creation of closed-loop blocks and associated connections
308 *
309 * @param model The model the block is associated with
310 * @param connections Vector storing the connections between blocks
311 * @param config The JSON configuration
312 * @param component Name of the component to retrieve from config
313 * @param closed_loop_bcs List of boundary conditions that should be connected
314 * to a closed loop heart block
315 */
316void create_closed_loop(
317 Model& model,
318 std::vector<std::tuple<std::string, std::string>>& connections,
319 const nlohmann::json& config, const std::string& component,
320 std::vector<std::string>& closed_loop_bcs);
321
322/**
323 * @brief Handle the creation of valves and their associated connections
324 *
325 * @param model The model the block is associated with
326 * @param connections Vector storing the connections between blocks
327 * @param config The JSON configuration
328 * @param component Name of the component to retrieve from config
329 */
330void create_valves(
331 Model& model,
332 std::vector<std::tuple<std::string, std::string>>& connections,
333 const nlohmann::json& config, const std::string& component);
334
335/**
336 * @brief Handle the creation of chambers
337 *
338 * @param model The model the block is associated with
339 * @param connections Vector storing the connections between blocks
340 * @param config The JSON configuration containing all the closed loop blocks
341 * @param component Name of the component to retrieve from config
342 */
343void create_chambers(
344 Model& model,
345 std::vector<std::tuple<std::string, std::string>>& connections,
346 const nlohmann::json& config, const std::string& component);
347
348#endif
Activation function classes for cardiac chamber models.
Active stress models for chamber blocks.
model::Model source file
Material models for the ChamberSphere block.
State source file.
const nlohmann::json & operator[](const char *key) const
Wrap error check around key retrieval (throws detailed error if key doesn't exist).
Definition SimulationParameters.h:103
JsonWrapper(const nlohmann::json &json, const std::string &component, const std::string &name_str, const int &id)
Wrap around JSON configuration with detailed error message in case key is not found in configuration.
Definition SimulationParameters.h:89
Model of 0D elements.
Definition Model.h:56
State of the system.
Definition State.h:19
DEBUG_MSG source file.
Simulation parameters.
Definition SimulationParameters.h:40
bool sim_coupled
Running 0D simulation coupled with external solver.
Definition SimulationParameters.h:68
int sim_nliter
Definition SimulationParameters.h:56
bool output_all_cycles
Output all cardiac cycles.
Definition SimulationParameters.h:66
int sim_pts_per_cycle
Number of time steps per cardiac cycle.
Definition SimulationParameters.h:47
int sim_num_time_steps
Total number of time steps.
Definition SimulationParameters.h:55
double sim_external_step_size
Definition SimulationParameters.h:70
double sim_time_step_size
Simulation time step size.
Definition SimulationParameters.h:43
int sim_num_cycles
Number of cardiac cycles to simulate.
Definition SimulationParameters.h:46
bool output_mean_only
Output only the mean value.
Definition SimulationParameters.h:64
bool sim_max_iter_error_to_warning
Definition SimulationParameters.h:72
bool sim_steady_initial
Start from steady solution.
Definition SimulationParameters.h:61
int output_interval
Interval of writing output.
Definition SimulationParameters.h:59
bool output_variable_based
Output variable based instead of vessel based.
Definition SimulationParameters.h:62
double sim_abs_tol
Absolute tolerance for simulation.
Definition SimulationParameters.h:44
double sim_cardiac_period
Cardiac period.
Definition SimulationParameters.h:45
bool output_derivative
Output derivatives.
Definition SimulationParameters.h:65
double sim_cycle_to_cycle_error
Cycle-to-cycle error.
Definition SimulationParameters.h:54
bool use_cycle_to_cycle_error
Definition SimulationParameters.h:48
double sim_rho_infty
Spectral radius of generalized-alpha.
Definition SimulationParameters.h:58