11#pragma once
22
3+ #include < cmath>
34#include < cstddef>
45#include < filesystem>
5- #include < format>
66#include < fstream>
77#include < iostream>
88#include < stdexcept>
@@ -30,7 +30,8 @@ namespace GridKit
3030 * @brief Describes an event that is used to modify the simulation at the
3131 * given time point
3232 *
33- * ContingencyAnalysis repeats fault events at each bus with the same R and X.
33+ * ContingencyAnalysis repeats fault events at each bus with the same R and
34+ * X.
3435 */
3536 struct SystemEvent
3637 {
@@ -72,6 +73,12 @@ namespace GridKit
7273 double rel_tol;
7374 // / absolute tolerance for the solver
7475 double abs_tol;
76+ // / relative residual tolerance for the co-simulation interface
77+ double cosim_rel_tol;
78+ // / scaled step tolerance for the co-simulation interface solver
79+ double cosim_step_tol;
80+ // / estimated relative error of co-simulation residual evaluations
81+ double cosim_function_error;
7582 // / fixed solver time step size, or 0 for adaptive stepping
7683 double dt_fixed;
7784 // / maximum number of solver time steps, or 0 for the IDA default
@@ -101,9 +108,12 @@ namespace GridKit
101108 using json = ::nlohmann::json;
102109 using Log = ::GridKit::Utilities::Logger;
103110
104- inline constexpr double DEFAULT_SOLVER_REL_TOL = 1.0e-7 ;
105- inline constexpr double DEFAULT_SOLVER_ABS_TOL = 1.0e-9 ;
106- inline constexpr double DEFAULT_VERIFICATION_TOL = 1.0e-4 ;
111+ inline constexpr double DEFAULT_SOLVER_REL_TOL = 1.0e-7 ;
112+ inline constexpr double DEFAULT_SOLVER_ABS_TOL = 1.0e-9 ;
113+ inline constexpr double DEFAULT_VERIFICATION_TOL = 1.0e-4 ;
114+ inline constexpr double DEFAULT_COSIM_REL_TOL = 1.0e-8 ;
115+ inline constexpr double DEFAULT_COSIM_STEP_TOL = 1.0e-12 ;
116+ inline constexpr double DEFAULT_COSIM_FUNCTION_ERROR = 1.0e-10 ;
107117
108118 /* *
109119 * @brief JSON parser implementation for `StudyData`
@@ -117,20 +127,38 @@ namespace GridKit
117127 j.at (" tmax" ).get_to (c.tmax );
118128 c.rel_tol = j.value (" rel_tol" , DEFAULT_SOLVER_REL_TOL );
119129 c.abs_tol = j.value (" abs_tol" , DEFAULT_SOLVER_ABS_TOL );
120- c.dt_fixed = j.value (" dt_fixed" , 0.0 );
121- c.max_steps = j.value (" max_steps" , std::size_t {0 });
122- c.max_order = j.value (" max_order" , 5 );
123- c.consistent_ic_type = AnalysisManager::Sundials::IdaConsistentICType::YA_YDP ;
130+ const auto tolerance = [&](const char * name, double fallback)
131+ {
132+ const double value = j.value (name, fallback);
133+ if (!std::isfinite (value) || value <= 0.0 )
134+ {
135+ throw std::invalid_argument (
136+ std::string (name) + " must be positive and finite" );
137+ }
138+ return value;
139+ };
140+ c.cosim_rel_tol = tolerance (" cosim_rel_tol" , DEFAULT_COSIM_REL_TOL );
141+ c.cosim_step_tol = tolerance (" cosim_step_tol" , DEFAULT_COSIM_STEP_TOL );
142+ c.cosim_function_error =
143+ tolerance (" cosim_function_error" , DEFAULT_COSIM_FUNCTION_ERROR );
144+ c.dt_fixed = j.value (" dt_fixed" , 0.0 );
145+ c.max_steps = j.value (" max_steps" , std::size_t {0 });
146+ c.max_order = j.value (" max_order" , 5 );
147+ c.consistent_ic_type =
148+ AnalysisManager::Sundials::IdaConsistentICType::YA_YDP ;
124149 if (j.contains (" consistent_ic_type" ))
125150 {
126- const auto consistent_ic_type_str = j.at (" consistent_ic_type" ).get <std::string>();
151+ const auto consistent_ic_type_str =
152+ j.at (" consistent_ic_type" ).get <std::string>();
127153 if (consistent_ic_type_str == " y" )
128154 {
129- c.consistent_ic_type = AnalysisManager::Sundials::IdaConsistentICType::Y;
155+ c.consistent_ic_type =
156+ AnalysisManager::Sundials::IdaConsistentICType::Y;
130157 }
131158 else if (consistent_ic_type_str == " ya_ydp" )
132159 {
133- c.consistent_ic_type = AnalysisManager::Sundials::IdaConsistentICType::YA_YDP ;
160+ c.consistent_ic_type =
161+ AnalysisManager::Sundials::IdaConsistentICType::YA_YDP ;
134162 }
135163 else
136164 {
@@ -223,7 +251,8 @@ namespace GridKit
223251 c.error_type = ErrorType::RELATIVE ;
224252 }
225253
226- c.abs_err_threshold = j.value (" abs_err_threshold" , Testing::DEFAULT_ABS_ERROR_THRESHOLD );
254+ c.abs_err_threshold =
255+ j.value (" abs_err_threshold" , Testing::DEFAULT_ABS_ERROR_THRESHOLD );
227256 }
228257
229258 /* *
@@ -302,7 +331,8 @@ namespace GridKit
302331 // output file must be a symlink to the model output file
303332 if (exists (data.output_file ))
304333 {
305- if ((!is_symlink (data.output_file )) || (read_symlink (data.output_file ) != model_output_file))
334+ if ((!is_symlink (data.output_file ))
335+ || (read_symlink (data.output_file ) != model_output_file))
306336 {
307337 Log::error () << " Study output file not usable" << std::endl;
308338 }
@@ -317,39 +347,23 @@ namespace GridKit
317347 return data;
318348 }
319349
320- void checkCommandLine (int argc, const std::string& appName)
321- {
322- if (argc < 2 )
323- {
324- Log::error () << " No input file provided\n "
325- << std::format (
326- " \n "
327- " Usage:\n "
328- " {} <json-input-file>\n "
329- " \n "
330- " Please provide a json input file for the study to run.\n "
331- " \n " ,
332- appName);
333- exit (1 );
334- }
335- }
336-
337350 Testing::TestStatus checkErrors (
338- const StudyData& study_data,
339- bool print_results = true )
351+ const StudyData& study_data, bool print_results = true )
340352 {
341- // Generate aggregate errors comparing variable output to reference solution
353+ // Generate aggregate errors comparing variable output to reference
354+ // solution
342355 auto func = std::string{" monitor file vs reference file" };
343356 auto status = Testing::TestStatus{func.c_str ()};
344357
345358 const auto & out_file = study_data.output_file ;
346359 const auto & ref_file = study_data.reference_file ;
347360 if (!out_file.empty () && !ref_file.empty ())
348361 {
349- auto errorSet = Testing::compareCSV (out_file,
350- ref_file,
351- study_data.error_type ,
352- study_data.abs_err_threshold );
362+ auto errorSet = Testing::compareCSV (
363+ out_file,
364+ ref_file,
365+ study_data.error_type ,
366+ study_data.abs_err_threshold );
353367
354368 // Print the errors
355369 if (print_results)
@@ -363,7 +377,8 @@ namespace GridKit
363377 status *= study_data.error_tol .size () == errorSet->var_errors .size ();
364378 for (std::size_t i = 0 ; i < study_data.error_tol .size (); ++i)
365379 {
366- status *= errorSet->var_errors [i].max_value < study_data.error_tol [i];
380+ status *=
381+ errorSet->var_errors [i].max_value < study_data.error_tol [i];
367382 }
368383 }
369384 else
0 commit comments