diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/job_adapter.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/job_adapter.hpp index 5899ca221..88e2929c8 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/job_adapter.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/job_adapter.hpp @@ -136,6 +136,7 @@ class JobAdapter> } CalculationInfo get_calculation_info_impl() const { return model_reference_.get().calculation_info(); } + void reset_calculation_info_impl() { model_reference_.get().reset_calculation_info(); } void thread_safe_add_calculation_info_impl(CalculationInfo const& info) { std::lock_guard const lock{calculation_info_mutex_}; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/job_dispatch.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/job_dispatch.hpp index 97f77634b..209f62b92 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/job_dispatch.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/job_dispatch.hpp @@ -24,6 +24,7 @@ class JobDispatch { static BatchParameter batch_calculation(Adapter& adapter, ResultDataset const& result_data, UpdateDataset const& update_data, Idx threading = sequential) { if (update_data.empty()) { + adapter.reset_calculation_info(); adapter.calculate(result_data); return BatchParameter{}; } @@ -38,6 +39,7 @@ class JobDispatch { } // calculate once to cache, ignore results + adapter.reset_calculation_info(); adapter.cache_calculate(); // error messages @@ -86,6 +88,7 @@ class JobDispatch { }; auto run = [&adapter, &result_data, &thread_info](Idx scenario_idx) { + adapter.reset_calculation_info(); adapter.calculate(result_data, scenario_idx); main_core::merge_into(thread_info, adapter.get_calculation_info()); }; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/job_interface.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/job_interface.hpp index 3210195fc..c6e97a207 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/job_interface.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/job_interface.hpp @@ -68,6 +68,13 @@ template class JobInterface { { return static_cast(this)->get_calculation_info_impl(); } + void reset_calculation_info() + requires requires(Adapter& adapter) { // NOSONAR + { adapter.reset_calculation_info_impl() } -> std::same_as; + } + { + static_cast(this)->reset_calculation_info_impl(); + } void thread_safe_add_calculation_info(CalculationInfo const& info) requires requires(Adapter& adapter) { // NOSONAR diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 60c757fdf..21564cb6e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -420,7 +420,6 @@ class MainModelImpl, ComponentLis using sym = typename SolverOutputType::sym; assert(construction_complete_); - calculation_info_ = CalculationInfo{}; // prepare auto const& input = [this, prepare_input_ = std::forward(prepare_input)] { Timer const timer{calculation_info_, LogEvent::prepare}; @@ -558,6 +557,8 @@ class MainModelImpl, ComponentLis assert(construction_complete_); main_core::merge_into(calculation_info_, info); } + void reset_calculation_info() { calculation_info_ = CalculationInfo{}; } + auto const& state() const { assert(construction_complete_); return state_; diff --git a/tests/benchmark_cpp/benchmark.cpp b/tests/benchmark_cpp/benchmark.cpp index 0fb2fca69..6312790cf 100644 --- a/tests/benchmark_cpp/benchmark.cpp +++ b/tests/benchmark_cpp/benchmark.cpp @@ -99,7 +99,7 @@ std::string make_key(LogEvent code) { } key += "\t"; } - key += common::logging::to_string(code); + key += to_string(code); return key; } diff --git a/tests/cpp_unit_tests/test_job_dispatch.cpp b/tests/cpp_unit_tests/test_job_dispatch.cpp index 0161cd4cd..a5cb496dd 100644 --- a/tests/cpp_unit_tests/test_job_dispatch.cpp +++ b/tests/cpp_unit_tests/test_job_dispatch.cpp @@ -33,6 +33,7 @@ struct CallCounter { std::atomic setup_calls{}; std::atomic winddown_calls{}; std::atomic thread_safe_add_calculation_info_calls{}; + std::atomic reset_calculation_info_calls{}; void reset_counters() { calculate_calls = 0; @@ -40,6 +41,7 @@ struct CallCounter { setup_calls = 0; winddown_calls = 0; thread_safe_add_calculation_info_calls = 0; + reset_calculation_info_calls = 0; } }; @@ -60,6 +62,7 @@ class JobAdapterMock : public JobInterface { Idx get_thread_safe_add_calculation_info_counter() const { return counter_->thread_safe_add_calculation_info_calls; } + Idx get_reset_calculation_info_counter() const { return counter_->reset_calculation_info_calls; } private: friend class JobInterface; @@ -77,6 +80,7 @@ class JobAdapterMock : public JobInterface { void thread_safe_add_calculation_info_impl(CalculationInfo const& /*info*/) const { ++(counter_->thread_safe_add_calculation_info_calls); } + void reset_calculation_info_impl() const { ++(counter_->reset_calculation_info_calls); } }; class SomeTestException : public std::runtime_error { @@ -102,6 +106,8 @@ TEST_CASE("Test job dispatch logic") { CHECK(expected_result == actual_result); CHECK(adapter.get_calculate_counter() == 1); CHECK(adapter.get_cache_calculate_counter() == 0); // no cache calculation in this case + CHECK(adapter.get_reset_calculation_info_counter() == + adapter.get_calculate_counter() + adapter.get_cache_calculate_counter()); } SUBCASE("No scenarios") { bool const has_data = true; @@ -113,6 +119,8 @@ TEST_CASE("Test job dispatch logic") { // no calculations should be done CHECK(adapter.get_calculate_counter() == 0); CHECK(adapter.get_cache_calculate_counter() == 0); + CHECK(adapter.get_reset_calculation_info_counter() == + adapter.get_calculate_counter() + adapter.get_cache_calculate_counter()); } SUBCASE("With scenarios and update data") { bool const has_data = true; @@ -125,6 +133,8 @@ TEST_CASE("Test job dispatch logic") { // n_scenarios calculations should be done as we run sequentially CHECK(adapter.get_calculate_counter() == n_scenarios); CHECK(adapter.get_cache_calculate_counter() == 1); // cache calculation is done + CHECK(adapter.get_reset_calculation_info_counter() == + adapter.get_calculate_counter() + adapter.get_cache_calculate_counter()); } } SUBCASE("Test single_thread_job") { @@ -151,6 +161,8 @@ TEST_CASE("Test job dispatch logic") { CHECK(adapter_.get_winddown_counter() == expected_calls); CHECK(adapter_.get_calculate_counter() == expected_calls); CHECK(adapter_.get_thread_safe_add_calculation_info_counter() == 1); // always called once + CHECK(adapter_.get_reset_calculation_info_counter() == + adapter_.get_calculate_counter() + adapter_.get_cache_calculate_counter()); }; adapter.prepare_job_dispatch(update_data); // replicate preparation step from batch_calculation