diff --git a/benchmarks/picca_2016/multi_slab/material_a b/benchmarks/picca_2016/multi_slab/material_a new file mode 100644 index 000000000..65e45d14c Binary files /dev/null and b/benchmarks/picca_2016/multi_slab/material_a differ diff --git a/benchmarks/picca_2016/multi_slab/material_b b/benchmarks/picca_2016/multi_slab/material_b new file mode 100644 index 000000000..860f0eb98 Binary files /dev/null and b/benchmarks/picca_2016/multi_slab/material_b differ diff --git a/benchmarks/picca_2016/multi_slab/multi_slab.material_map b/benchmarks/picca_2016/multi_slab/multi_slab.material_map new file mode 100644 index 000000000..0697a91c9 --- /dev/null +++ b/benchmarks/picca_2016/multi_slab/multi_slab.material_map @@ -0,0 +1 @@ +0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 \ No newline at end of file diff --git a/benchmarks/picca_2016/multi_slab/multi_slab.prm b/benchmarks/picca_2016/multi_slab/multi_slab.prm new file mode 100644 index 000000000..7150021d3 --- /dev/null +++ b/benchmarks/picca_2016/multi_slab/multi_slab.prm @@ -0,0 +1,21 @@ +set problem dimension = 1 +set transport model = saaf +set number of groups = 1 +set angular quadrature name = gauss_legendre +set angular quadrature order = 4 +set do eigenvalue calculations = true +set reflective boundary names = + +set x, y, z max values of boundary locations = 21 +set number of cells for x, y, z directions = 21 +set uniform refinements = 4 +set number of materials = 2 + +set finite element polynomial degree = 1 + +set output file name base = multi_slab + +subsection material ID map +set material id file name map = 0: material_a, 1: material_b +set material id file name = multi_slab.material_map +end \ No newline at end of file diff --git a/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh.prm b/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh.prm new file mode 100644 index 000000000..9bf46e66a --- /dev/null +++ b/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh.prm @@ -0,0 +1,22 @@ +set problem dimension = 1 +set transport model = saaf +set number of groups = 1 +set angular quadrature name = gauss_legendre +set angular quadrature order = 4 +set do eigenvalue calculations = true +set reflective boundary names = + +set x, y, z max values of boundary locations = 21 +set number of cells for x, y, z directions = 21 +set uniform refinements = 4 +set number of materials = 2 + +set finite element polynomial degree = 1 +set k_effective updater type = rayleigh quotient + +set output file name base = multi_slab_rayleigh + +subsection material ID map +set material id file name map = 0: material_a, 1: material_b +set material id file name = multi_slab.material_map +end \ No newline at end of file diff --git a/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh_nda.prm b/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh_nda.prm new file mode 100644 index 000000000..7cfe57f34 --- /dev/null +++ b/benchmarks/picca_2016/multi_slab/multi_slab_rayleigh_nda.prm @@ -0,0 +1,23 @@ +set problem dimension = 1 +set transport model = saaf +set number of groups = 1 +set angular quadrature name = gauss_legendre +set angular quadrature order = 4 +set do eigenvalue calculations = true +set reflective boundary names = + +set x, y, z max values of boundary locations = 21 +set number of cells for x, y, z directions = 21 +set uniform refinements = 4 +set number of materials = 2 + +set finite element polynomial degree = 1 +set k_effective updater type = rayleigh quotient + +set output file name base = multi_slab_rayleigh +set do nda = true + +subsection material ID map +set material id file name map = 0: material_a, 1: material_b +set material id file name = multi_slab.material_map +end \ No newline at end of file diff --git a/codecov.yml b/codecov.yml index 605852c10..ad8b51d2b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,11 @@ +coverage: + status: + project: + default: + target: 95% + patch: + default: + target: 95% ignore: - "**/tests/*" - "**/BART/inc/**/*" diff --git a/src/domain/definition.h b/src/domain/definition.h index 5d057158d..1b86941cd 100644 --- a/src/domain/definition.h +++ b/src/domain/definition.h @@ -13,7 +13,7 @@ #include "domain/definition_i.h" #include "domain/finite_element/finite_element_i.h" #include "domain/mesh/mesh_i.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "system/system_types.h" namespace bart { diff --git a/src/domain/definition_i.h b/src/domain/definition_i.h index d6f03d368..8cf293862 100644 --- a/src/domain/definition_i.h +++ b/src/domain/definition_i.h @@ -9,7 +9,7 @@ #include #include "domain/domain_types.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "system/system_types.h" #include "utility/has_description.h" diff --git a/src/domain/finite_element/finite_element_gaussian.h b/src/domain/finite_element/finite_element_gaussian.h index 79b47dd42..083aa722e 100644 --- a/src/domain/finite_element/finite_element_gaussian.h +++ b/src/domain/finite_element/finite_element_gaussian.h @@ -4,7 +4,7 @@ #include #include "domain/finite_element/finite_element.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" namespace bart { diff --git a/src/domain/finite_element/tests/finite_element_gaussian_test.cpp b/src/domain/finite_element/tests/finite_element_gaussian_test.cpp index c2b4f8076..9a4765dbd 100644 --- a/src/domain/finite_element/tests/finite_element_gaussian_test.cpp +++ b/src/domain/finite_element/tests/finite_element_gaussian_test.cpp @@ -9,7 +9,7 @@ #include #include -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "finite_element_test.hpp" #include "test_helpers/gmock_wrapper.h" diff --git a/src/domain/mesh/mesh_cartesian.cpp b/src/domain/mesh/mesh_cartesian.cpp index df373dc8e..43282a5d4 100644 --- a/src/domain/mesh/mesh_cartesian.cpp +++ b/src/domain/mesh/mesh_cartesian.cpp @@ -10,7 +10,7 @@ #include #include "domain/mesh/factory.hpp" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" namespace bart::domain::mesh { diff --git a/src/domain/mesh/tests/mesh_cartesian_test.cpp b/src/domain/mesh/tests/mesh_cartesian_test.cpp index 0125d72c6..078c12386 100644 --- a/src/domain/mesh/tests/mesh_cartesian_test.cpp +++ b/src/domain/mesh/tests/mesh_cartesian_test.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include "test_helpers/test_helper_functions.h" #include "test_helpers/gmock_wrapper.h" diff --git a/src/domain/tests/definition_mock.h b/src/domain/tests/definition_mock.h index eeb9d96a7..a94493585 100644 --- a/src/domain/tests/definition_mock.h +++ b/src/domain/tests/definition_mock.h @@ -7,7 +7,7 @@ #include #include "domain/definition_i.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "test_helpers/gmock_wrapper.h" diff --git a/src/domain/tests/definition_test.cpp b/src/domain/tests/definition_test.cpp index e716dcdc9..671c34921 100644 --- a/src/domain/tests/definition_test.cpp +++ b/src/domain/tests/definition_test.cpp @@ -13,7 +13,7 @@ #include "test_helpers/gmock_wrapper.h" #include "domain/mesh/tests/mesh_mock.h" #include "domain/finite_element/tests/finite_element_mock.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" namespace { diff --git a/src/formulation/updater/diffusion_updater.hpp b/src/formulation/updater/diffusion_updater.hpp index bd427d2df..18bea2d75 100644 --- a/src/formulation/updater/diffusion_updater.hpp +++ b/src/formulation/updater/diffusion_updater.hpp @@ -12,7 +12,7 @@ #include "formulation/updater/scattering_source_updater_i.h" #include "formulation/updater/fission_source_updater_i.h" #include "quadrature/quadrature_set_i.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "utility/has_description.h" namespace bart { diff --git a/src/formulation/updater/saaf_updater.h b/src/formulation/updater/saaf_updater.h index 4ff81c44c..c88c5d565 100644 --- a/src/formulation/updater/saaf_updater.h +++ b/src/formulation/updater/saaf_updater.h @@ -11,7 +11,7 @@ #include "formulation/updater/scattering_source_updater_i.h" #include "formulation/updater/fission_source_updater_i.h" #include "quadrature/quadrature_set_i.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "system/solution/solution_types.h" #include "utility/has_description.h" diff --git a/src/formulation/updater/tests/updater_tests.h b/src/formulation/updater/tests/updater_tests.h index 6fa600076..3efe8e4b7 100644 --- a/src/formulation/updater/tests/updater_tests.h +++ b/src/formulation/updater/tests/updater_tests.h @@ -14,7 +14,7 @@ #include "test_helpers/gmock_wrapper.h" #include "test_helpers/test_helper_functions.h" #include "test_helpers/dealii_test_domain.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" namespace bart { diff --git a/src/framework/builder/framework_builder.cpp b/src/framework/builder/framework_builder.cpp index 2964cbd01..93e26b7b2 100644 --- a/src/framework/builder/framework_builder.cpp +++ b/src/framework/builder/framework_builder.cpp @@ -49,6 +49,7 @@ // Iteration classes #include "iteration/initializer/initialize_fixed_terms_once.h" +#include "iteration/initializer/initialize_fixed_terms_reset_moments.hpp" #include "iteration/group/group_solve_iteration.h" #include "iteration/group/group_source_iteration.h" #include "iteration/outer/outer_power_iteration.hpp" @@ -350,18 +351,31 @@ auto FrameworkBuilder::BuildGroupSolution(const int n_angles) -> std::uniqu template auto FrameworkBuilder::BuildInitializer(const std::shared_ptr& updater_ptr, const int total_groups, - const int total_angles) -> std::unique_ptr { + const int total_angles, + const InitializerName implementation) -> std::unique_ptr { ReportBuildingComponant("Initializer"); std::unique_ptr return_ptr = nullptr; - using InitializeOnceType = iteration::initializer::InitializeFixedTermsOnce; + if (implementation == InitializerName::kInitializeFixedTermsOnce) { + using InitializeOnceType = iteration::initializer::InitializeFixedTermsOnce; + return_ptr = std::move(std::make_unique(updater_ptr, total_groups, total_angles)); + } else if (implementation == InitializerName::kInitializeFixedTermsAndResetMoments) { + using InitializeAndResetMoments = iteration::initializer::InitializeFixedTermsResetMoments; + return_ptr = std::move(std::make_unique(updater_ptr, total_groups, total_angles)); + } - return_ptr = std::move(std::make_unique(updater_ptr, total_groups, total_angles)); ReportBuildSuccess(return_ptr->description()); return return_ptr; } +template +auto FrameworkBuilder::BuildInitializer(const std::shared_ptr& updater_ptr, + const int total_groups, + const int total_angles) -> std::unique_ptr { + return BuildInitializer(updater_ptr, total_groups, total_angles, InitializerName::kInitializeFixedTermsOnce); +} + template auto FrameworkBuilder::BuildKEffectiveUpdater() -> std::unique_ptr { using ReturnType = eigenvalue::k_effective::UpdaterViaRayleighQuotient; diff --git a/src/framework/builder/framework_builder.hpp b/src/framework/builder/framework_builder.hpp index 88a619734..626d5d6de 100644 --- a/src/framework/builder/framework_builder.hpp +++ b/src/framework/builder/framework_builder.hpp @@ -56,6 +56,7 @@ class FrameworkBuilder : public data_port::StatusDataPort, public FrameworkBuild using typename FrameworkBuilderI::DiffusionFormulationImpl; using typename FrameworkBuilderI::MomentCalculatorImpl; + using typename FrameworkBuilderI::InitializerName; using typename FrameworkBuilderI::ColorStatusPair; using typename FrameworkBuilderI::ColorStatusInstrument; @@ -100,6 +101,10 @@ class FrameworkBuilder : public data_port::StatusDataPort, public FrameworkBuild [[nodiscard]] auto BuildInitializer(const std::shared_ptr&, const int total_groups, const int total_angles) -> std::unique_ptr override; + [[nodiscard]] auto BuildInitializer(const std::shared_ptr&, + const int total_groups, + const int total_angles, + const InitializerName) -> std::unique_ptr override; [[nodiscard]] auto BuildKEffectiveUpdater() -> std::unique_ptr override; [[nodiscard]] auto BuildKEffectiveUpdater( const std::shared_ptr&, diff --git a/src/framework/builder/framework_builder_i.hpp b/src/framework/builder/framework_builder_i.hpp index 0bfc7768e..b4a907bc9 100644 --- a/src/framework/builder/framework_builder_i.hpp +++ b/src/framework/builder/framework_builder_i.hpp @@ -26,10 +26,11 @@ #include "iteration/group/group_solve_iteration_i.h" #include "iteration/outer/outer_iteration_i.hpp" #include "iteration/subroutine/subroutine_i.hpp" +#include "iteration/initializer/factory.hpp" #include "quadrature/calculators/spherical_harmonic_moments_i.h" #include "quadrature/calculators/angular_flux_integrator_i.hpp" #include "quadrature/quadrature_set_i.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "solver/group/single_group_solver_i.h" #include "system/moments/spherical_harmonic_i.h" #include "system/moments/spherical_harmonic_types.h" @@ -79,6 +80,7 @@ class FrameworkBuilderI { // Implementation specifiers using DiffusionFormulationImpl = formulation::DiffusionFormulationImpl; + using InitializerName = iteration::initializer::InitializerName; using MomentCalculatorImpl = quadrature::MomentCalculatorImpl; using SubroutineName = iteration::subroutine::SubroutineName; @@ -126,6 +128,10 @@ class FrameworkBuilderI { virtual auto BuildInitializer(const std::shared_ptr&, const int total_groups, const int total_angles) -> std::unique_ptr = 0; + virtual auto BuildInitializer(const std::shared_ptr&, + const int total_groups, + const int total_angles, + const InitializerName) -> std::unique_ptr = 0; virtual auto BuildKEffectiveUpdater() -> std::unique_ptr = 0; virtual auto BuildKEffectiveUpdater( const std::shared_ptr&, diff --git a/src/framework/builder/framework_validator.cpp b/src/framework/builder/framework_validator.cpp index df0bf6f2f..064a66fed 100644 --- a/src/framework/builder/framework_validator.cpp +++ b/src/framework/builder/framework_validator.cpp @@ -32,26 +32,10 @@ auto FrameworkValidator::Parse(const framework::FrameworkParameters parameters) } // Check for required angular solution storage - if (!parameters.reflective_boundaries.empty() && - parameters.equation_type == problem::EquationType::kSelfAdjointAngularFlux) { - needed_parts_.insert(FrameworkPart::AngularSolutionStorage); - } -} - -void FrameworkValidator::Parse(const problem::ParametersI& to_parse) { - needed_parts_ = {FrameworkPart::ScatteringSourceUpdate}; - if (to_parse.IsEigenvalueProblem()) - needed_parts_.insert(FrameworkPart::FissionSourceUpdate); - - const auto reflective_boundary = to_parse.ReflectiveBoundary(); - bool has_reflective = std::any_of( - reflective_boundary.begin(), - reflective_boundary.end(), - [](std::pair pair){ return pair.second; }); - - if (has_reflective && - to_parse.TransportModel() == problem::EquationType::kSelfAdjointAngularFlux) { + if (const bool equation_type_is_saaf{ parameters.equation_type == problem::EquationType::kSelfAdjointAngularFlux}; + parameters.use_nda_ || (!parameters.reflective_boundaries.empty() && equation_type_is_saaf)) { needed_parts_.insert(FrameworkPart::AngularSolutionStorage); + if (parameters.use_nda_) AssertThrow(equation_type_is_saaf, dealii::ExcMessage("NDA requires angular solve")) } } diff --git a/src/framework/builder/framework_validator.hpp b/src/framework/builder/framework_validator.hpp index f507bfde2..c04754347 100644 --- a/src/framework/builder/framework_validator.hpp +++ b/src/framework/builder/framework_validator.hpp @@ -20,7 +20,6 @@ class FrameworkValidator : public FrameworkValidatorI, public: auto AddPart(const FrameworkPart to_add) -> FrameworkValidator& override; auto Parse(const framework::FrameworkParameters) -> void override; - auto Parse(const problem::ParametersI& to_parse) -> void override; auto ReportValidation() -> void override; [[nodiscard]] auto HasNeededParts() const -> bool override { return needed_parts_.size() > 0; } diff --git a/src/framework/builder/framework_validator_i.hpp b/src/framework/builder/framework_validator_i.hpp index b1940fb83..07ac09d43 100644 --- a/src/framework/builder/framework_validator_i.hpp +++ b/src/framework/builder/framework_validator_i.hpp @@ -19,7 +19,6 @@ class FrameworkValidatorI { virtual ~FrameworkValidatorI() = default; virtual auto AddPart(const FrameworkPart to_add) -> FrameworkValidatorI& = 0; virtual auto Parse(const framework::FrameworkParameters) -> void = 0; - virtual auto Parse(const problem::ParametersI& to_parse) -> void = 0; virtual auto ReportValidation() -> void = 0; virtual auto HasNeededParts() const -> bool = 0; diff --git a/src/framework/builder/tests/framework_builder_integration_tests.cpp b/src/framework/builder/tests/framework_builder_integration_tests.cpp index 4e36cdc95..103caf978 100644 --- a/src/framework/builder/tests/framework_builder_integration_tests.cpp +++ b/src/framework/builder/tests/framework_builder_integration_tests.cpp @@ -36,6 +36,7 @@ #include "solver/group/single_group_solver.h" #include "system/solution/mpi_group_angular_solution.h" #include "iteration/initializer/initialize_fixed_terms_once.h" +#include "iteration/initializer/initialize_fixed_terms_reset_moments.hpp" #include "iteration/group/group_source_iteration.h" #include "iteration/subroutine/get_scalar_flux_from_framework.hpp" #include "system/system_types.h" @@ -877,9 +878,9 @@ TYPED_TEST(FrameworkBuilderIntegrationTest, BuildSystem) { class FrameworkBuilderIntegrationNonDimTest : public FrameworkBuilderIntegrationTest {}; -TEST_F(FrameworkBuilderIntegrationNonDimTest, BuildInitializer) { - auto fixed_updater_ptr = - std::make_shared(); +TEST_F(FrameworkBuilderIntegrationNonDimTest, BuildDefaultInitializer) { + using InitializerName = iteration::initializer::InitializerName; + auto fixed_updater_ptr = std::make_shared(); using ExpectedType = iteration::initializer::InitializeFixedTermsOnce; const int total_groups = bart::test_helpers::RandomDouble(1, 10); @@ -895,4 +896,42 @@ TEST_F(FrameworkBuilderIntegrationNonDimTest, BuildInitializer) { EXPECT_EQ(dynamic_ptr->total_groups(), total_groups); } +TEST_F(FrameworkBuilderIntegrationNonDimTest, BuildInitializerFixedOnceSpecified) { + using InitializerName = iteration::initializer::InitializerName; + auto fixed_updater_ptr = std::make_shared(); + + using ExpectedType = iteration::initializer::InitializeFixedTermsOnce; + const int total_groups = bart::test_helpers::RandomDouble(1, 10); + const int total_angles = total_groups + 1; + + auto initializer_ptr = this->test_builder_ptr_->BuildInitializer(fixed_updater_ptr, + total_groups, + total_angles, + InitializerName::kInitializeFixedTermsOnce); + auto dynamic_ptr = dynamic_cast(initializer_ptr.get()); + ASSERT_NE(initializer_ptr, nullptr); + ASSERT_NE(dynamic_ptr, nullptr); + EXPECT_EQ(dynamic_ptr->total_angles(), total_angles); + EXPECT_EQ(dynamic_ptr->total_groups(), total_groups); +} + +TEST_F(FrameworkBuilderIntegrationNonDimTest, BuildInitializerResetMoments) { + using InitializerName = iteration::initializer::InitializerName; + auto fixed_updater_ptr = std::make_shared(); + + using ExpectedType = iteration::initializer::InitializeFixedTermsResetMoments; + const int total_groups = bart::test_helpers::RandomDouble(1, 10); + const int total_angles = total_groups + 1; + + auto initializer_ptr = this->test_builder_ptr_->BuildInitializer(fixed_updater_ptr, + total_groups, + total_angles, + InitializerName::kInitializeFixedTermsAndResetMoments); + auto dynamic_ptr = dynamic_cast(initializer_ptr.get()); + ASSERT_NE(initializer_ptr, nullptr); + ASSERT_NE(dynamic_ptr, nullptr); + EXPECT_EQ(dynamic_ptr->total_angles(), total_angles); + EXPECT_EQ(dynamic_ptr->total_groups(), total_groups); +} + } // namespace diff --git a/src/framework/builder/tests/framework_builder_mock.hpp b/src/framework/builder/tests/framework_builder_mock.hpp index 55ff0d307..5238d2d16 100644 --- a/src/framework/builder/tests/framework_builder_mock.hpp +++ b/src/framework/builder/tests/framework_builder_mock.hpp @@ -19,6 +19,7 @@ class FrameworkBuilderMock : public FrameworkBuilderI { using typename FrameworkBuilderI::GroupSolution; using typename FrameworkBuilderI::GroupSolveIteration; using typename FrameworkBuilderI::Initializer; + using typename FrameworkBuilderI::InitializerName; using typename FrameworkBuilderI::KEffectiveUpdater; using typename FrameworkBuilderI::MomentCalculator; using typename FrameworkBuilderI::MomentConvergenceChecker; @@ -69,6 +70,8 @@ class FrameworkBuilderMock : public FrameworkBuilderI { std::unique_ptr), (override)); MOCK_METHOD(std::unique_ptr, BuildInitializer, (const std::shared_ptr&, const int total_groups, const int total_angles), (override)); + MOCK_METHOD(std::unique_ptr, BuildInitializer, (const std::shared_ptr&, + const int total_groups, const int total_angles, const InitializerName), (override)); MOCK_METHOD(std::unique_ptr, BuildKEffectiveUpdater, (), (override)); MOCK_METHOD(std::unique_ptr, BuildKEffectiveUpdater, (const std::shared_ptr&, const std::shared_ptr&, const std::shared_ptr&), (override)); diff --git a/src/framework/builder/tests/framework_validator_mock.hpp b/src/framework/builder/tests/framework_validator_mock.hpp index 6a76cdf78..8573984c9 100644 --- a/src/framework/builder/tests/framework_validator_mock.hpp +++ b/src/framework/builder/tests/framework_validator_mock.hpp @@ -10,7 +10,6 @@ class FrameworkValidatorMock : public FrameworkValidatorI { public: MOCK_METHOD(FrameworkValidatorI&, AddPart, (const FrameworkPart to_add), (override)); MOCK_METHOD(void, Parse, (const framework::FrameworkParameters), (override)); - MOCK_METHOD(void, Parse, (const problem::ParametersI& to_parse), (override)); MOCK_METHOD(void, ReportValidation, (), (override)); MOCK_METHOD(bool, HasNeededParts, (), (override, const )); diff --git a/src/framework/builder/tests/framework_validator_parameters_test.cpp b/src/framework/builder/tests/framework_validator_parameters_test.cpp index 276312b66..8fc8790c7 100644 --- a/src/framework/builder/tests/framework_validator_parameters_test.cpp +++ b/src/framework/builder/tests/framework_validator_parameters_test.cpp @@ -4,7 +4,7 @@ #include "instrumentation/tests/instrument_mock.h" #include "test_helpers/gmock_wrapper.h" #include "test_helpers/test_helper_functions.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "utility/colors.hpp" namespace { @@ -89,6 +89,22 @@ TEST_F(FrameworkBuilderFrameworkValidatorParametersTest, SAAFRequiresAngularSolu EXPECT_TRUE(test_validator_.NeededParts().contains(Part::AngularSolutionStorage)); } +TEST_F(FrameworkBuilderFrameworkValidatorParametersTest, FrameworkNDAHasAngularStorage) { + FrameworkParameters nda_parameters{ framework_parameters_ }; + nda_parameters.use_nda_ = true; + nda_parameters.equation_type = problem::EquationType::kSelfAdjointAngularFlux; + + EXPECT_NO_THROW(test_validator_.Parse(nda_parameters)); + EXPECT_TRUE(test_validator_.NeededParts().contains(Part::AngularSolutionStorage)); +} + +TEST_F(FrameworkBuilderFrameworkValidatorParametersTest, FrameworkNDABadEquationType) { + FrameworkParameters nda_parameters{ framework_parameters_ }; + nda_parameters.use_nda_ = true; + nda_parameters.equation_type = problem::EquationType::kDiffusion; + + EXPECT_ANY_THROW(test_validator_.Parse(nda_parameters)); +} } // namespace diff --git a/src/framework/builder/tests/framework_validator_test.cpp b/src/framework/builder/tests/framework_validator_test.cpp index 424876212..6098330d7 100644 --- a/src/framework/builder/tests/framework_validator_test.cpp +++ b/src/framework/builder/tests/framework_validator_test.cpp @@ -1,6 +1,6 @@ #include "framework/builder/framework_validator.hpp" -#include "problem/tests/parameters_mock.h" +#include "framework/framework_parameters.hpp" #include "test_helpers/gmock_wrapper.h" #include "instrumentation/tests/instrument_mock.h" #include "utility/colors.hpp" @@ -20,7 +20,7 @@ class FrameworkBuilderFrameworkValidatorTest : public ::testing::Test { public: using StatusInstrumentType = instrumentation::InstrumentMock>; std::unique_ptr test_validator; - NiceMock mock_parameters; + framework::FrameworkParameters framework_parameters_; std::shared_ptr> mock_instrument; void SetUp() override; @@ -28,154 +28,67 @@ class FrameworkBuilderFrameworkValidatorTest : public ::testing::Test { void FrameworkBuilderFrameworkValidatorTest::SetUp() { using Boundary = problem::Boundary; - ON_CALL(mock_parameters, IsEigenvalueProblem()) - .WillByDefault(Return(true)); - ON_CALL(mock_parameters, TransportModel()) - .WillByDefault(Return(problem::EquationType::kDiffusion)); - ON_CALL(mock_parameters, ReflectiveBoundary()) - .WillByDefault(Return(std::map{ - {Boundary::kXMin, false}, - {Boundary::kXMax, false}})); + framework_parameters_.eigen_solver_type = problem::EigenSolverType::kPowerIteration; + framework_parameters_.equation_type = problem::EquationType::kDiffusion; + framework_parameters_.reflective_boundaries = {Boundary::kXMin, Boundary::kXMax}; + test_validator = std::make_unique(); mock_instrument = std::make_shared>(); using ValidationStatusPort = framework::builder::data_port::ValidatorStatusPort; - instrumentation::GetPort(*test_validator) - .AddInstrument(mock_instrument); + instrumentation::GetPort(*test_validator).AddInstrument(mock_instrument); } -TEST_F(FrameworkBuilderFrameworkValidatorTest, ParseTestNonEigenvalue) { - EXPECT_FALSE(test_validator->HasNeededParts()); - - EXPECT_CALL(mock_parameters, IsEigenvalueProblem()) - .WillOnce(Return(false)); - - test_validator->Parse(mock_parameters); - - EXPECT_TRUE(test_validator->HasNeededParts()); - EXPECT_THAT(test_validator->NeededParts(), - UnorderedElementsAreArray({Part::ScatteringSourceUpdate})); - EXPECT_FALSE(test_validator->HasUnneededParts()); - EXPECT_EQ(test_validator->UnneededParts().size(), 0); - EXPECT_TRUE(test_validator->Parts().empty()); -} - -TEST_F(FrameworkBuilderFrameworkValidatorTest, ParseTestEigenvalue) { - EXPECT_FALSE(test_validator->HasNeededParts()); - - EXPECT_CALL(mock_parameters, IsEigenvalueProblem()) - .WillOnce(DoDefault()); - - test_validator->Parse(mock_parameters); - - EXPECT_TRUE(test_validator->HasNeededParts()); - EXPECT_THAT(test_validator->NeededParts(), - UnorderedElementsAreArray({Part::FissionSourceUpdate, - Part::ScatteringSourceUpdate})); - EXPECT_TRUE(test_validator->Parts().empty()); -} - -TEST_F(FrameworkBuilderFrameworkValidatorTest, ParseTestSAAFWithoutReflective) { - EXPECT_FALSE(test_validator->HasNeededParts()); - - EXPECT_CALL(mock_parameters, TransportModel()) - .Times(::testing::AnyNumber()) - .WillRepeatedly(Return(problem::EquationType::kSelfAdjointAngularFlux)); - - test_validator->Parse(mock_parameters); - - EXPECT_TRUE(test_validator->HasNeededParts()); - EXPECT_THAT(test_validator->NeededParts(), - UnorderedElementsAreArray({Part::FissionSourceUpdate, - Part::ScatteringSourceUpdate})); - EXPECT_TRUE(test_validator->Parts().empty()); -} +TEST_F(FrameworkBuilderFrameworkValidatorTest, AddPart) { + test_validator->Parse(framework_parameters_); -TEST_F(FrameworkBuilderFrameworkValidatorTest, ParseTestSAAFWithReflective) { - using Boundary = problem::Boundary; - EXPECT_FALSE(test_validator->HasNeededParts()); - - EXPECT_CALL(mock_parameters, TransportModel()) - .WillOnce(Return(problem::EquationType::kSelfAdjointAngularFlux)); - EXPECT_CALL(mock_parameters, ReflectiveBoundary()) - .WillOnce(Return(std::map{ - {Boundary::kXMin, true}, - {Boundary::kXMax, false}})); - - test_validator->Parse(mock_parameters); - - EXPECT_TRUE(test_validator->HasNeededParts()); - EXPECT_THAT(test_validator->NeededParts(), - UnorderedElementsAreArray({Part::FissionSourceUpdate, - Part::ScatteringSourceUpdate, - Part::AngularSolutionStorage})); EXPECT_TRUE(test_validator->Parts().empty()); -} + test_validator->AddPart(Part::ScatteringSourceUpdate).AddPart(Part::FissionSourceUpdate); -TEST_F(FrameworkBuilderFrameworkValidatorTest, AddPart) { - test_validator->Parse(mock_parameters); - EXPECT_TRUE(test_validator->Parts().empty()); - test_validator->AddPart(Part::ScatteringSourceUpdate) - .AddPart(Part::FissionSourceUpdate); - EXPECT_THAT(test_validator->NeededParts(), - UnorderedElementsAreArray({Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate})); - EXPECT_THAT(test_validator->Parts(), - UnorderedElementsAreArray({Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate})); + EXPECT_THAT(test_validator->NeededParts(), UnorderedElementsAreArray({Part::ScatteringSourceUpdate, + Part::FissionSourceUpdate})); + EXPECT_THAT(test_validator->Parts(), UnorderedElementsAreArray({Part::ScatteringSourceUpdate, + Part::FissionSourceUpdate})); EXPECT_FALSE(test_validator->HasUnneededParts()); EXPECT_TRUE(test_validator->UnneededParts().empty()); test_validator->AddPart(Part::AngularSolutionStorage); - EXPECT_THAT(test_validator->Parts(), - UnorderedElementsAreArray({Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate, - Part::AngularSolutionStorage})); + EXPECT_THAT(test_validator->Parts(), UnorderedElementsAreArray({Part::ScatteringSourceUpdate, + Part::FissionSourceUpdate, + Part::AngularSolutionStorage})); EXPECT_TRUE(test_validator->HasUnneededParts()); - EXPECT_THAT(test_validator->UnneededParts(), - UnorderedElementsAreArray({Part::AngularSolutionStorage})); + EXPECT_THAT(test_validator->UnneededParts(), UnorderedElementsAreArray({Part::AngularSolutionStorage})); } TEST_F(FrameworkBuilderFrameworkValidatorTest, ReportValidationMissing) { - test_validator->Parse(mock_parameters); - - std::set expected_parts{Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate}; - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))) - .Times(::testing::AtLeast(1)); - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kRed))) - .Times(::testing::AtLeast(2)); + test_validator->Parse(framework_parameters_); + + std::set expected_parts{Part::ScatteringSourceUpdate, Part::FissionSourceUpdate}; + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))).Times(::testing::AtLeast(1)); + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kRed))).Times(::testing::AtLeast(2)); EXPECT_CALL(*mock_instrument, Read(Pair(_,utility::Color::kYellow))); test_validator->ReportValidation(); } TEST_F(FrameworkBuilderFrameworkValidatorTest, ReportValidationPresent) { - test_validator->Parse(mock_parameters); + test_validator->Parse(framework_parameters_); - std::set expected_parts{Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate}; + std::set expected_parts{Part::ScatteringSourceUpdate, Part::FissionSourceUpdate}; EXPECT_EQ(test_validator->NeededParts(), expected_parts); - test_validator->AddPart(Part::ScatteringSourceUpdate) - .AddPart(Part::FissionSourceUpdate); - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))) - .Times(::testing::AtLeast(1)); - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kGreen))) - .Times(::testing::AtLeast(2)); + test_validator->AddPart(Part::ScatteringSourceUpdate).AddPart(Part::FissionSourceUpdate); + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))).Times(::testing::AtLeast(1)); + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kGreen))).Times(::testing::AtLeast(2)); test_validator->ReportValidation(); } TEST_F(FrameworkBuilderFrameworkValidatorTest, ReportValidationMixed) { - test_validator->Parse(mock_parameters); + test_validator->Parse(framework_parameters_); - std::set expected_parts{Part::ScatteringSourceUpdate, - Part::FissionSourceUpdate}; + std::set expected_parts{Part::ScatteringSourceUpdate, Part::FissionSourceUpdate}; - test_validator->AddPart(Part::ScatteringSourceUpdate) - .AddPart(Part::AngularSolutionStorage); - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))) - .Times(::testing::AtLeast(1)); + test_validator->AddPart(Part::ScatteringSourceUpdate).AddPart(Part::AngularSolutionStorage); + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kReset))).Times(::testing::AtLeast(1)); EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kGreen))); - EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kYellow))) - .Times(2); + EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kYellow))).Times(2); EXPECT_CALL(*mock_instrument, Read(Pair(_, utility::Color::kRed))); test_validator->ReportValidation(); diff --git a/src/framework/framework_helper.cpp b/src/framework/framework_helper.cpp index 569e34a11..ac3488e19 100644 --- a/src/framework/framework_helper.cpp +++ b/src/framework/framework_helper.cpp @@ -4,6 +4,7 @@ #include "framework/framework.hpp" #include "framework/builder/framework_validator.hpp" #include "instrumentation/builder/instrument_builder.hpp" +#include "instrumentation/converter/convert_to_string/convergence_to_string.h" #include "material/material_protobuf.h" #include "iteration/outer/outer_iteration.hpp" #include "results/output_dealii_vtu.h" @@ -48,7 +49,8 @@ auto FrameworkHelper::ToFrameworkParameters( .number_of_cells{ framework::FrameworkParameters::NumberOfCells(problem_parameters.NCells()) }, .uniform_refinements{ problem_parameters.UniformRefinements() }, .discretization_type{ problem_parameters.Discretization() }, - .polynomial_degree{ framework::FrameworkParameters::PolynomialDegree(problem_parameters.FEPolynomialDegree()) } + .polynomial_degree{ framework::FrameworkParameters::PolynomialDegree(problem_parameters.FEPolynomialDegree()) }, + .use_nda_{ problem_parameters.DoNDA() } }; std::set reflective_boundaries; @@ -88,7 +90,7 @@ auto FrameworkHelper::ToFrameworkParameters( template auto FrameworkHelper::BuildFramework( builder::FrameworkBuilderI& builder, - const framework::FrameworkParameters& parameters) -> std::unique_ptr { + framework::FrameworkParameters& parameters) -> std::unique_ptr { using FrameworkPart = framework::builder::FrameworkPart; using MomentCalculator = typename builder::FrameworkBuilderI::MomentCalculator; using OuterIteration = typename builder::FrameworkBuilderI::OuterIteration; @@ -99,6 +101,15 @@ auto FrameworkHelper::BuildFramework( using ColorStringPair = std::pair; + // Check that if Drift-Diffusion formujlation is specified that we have the required dependencies provided + if (parameters.equation_type == problem::EquationType::kDriftDiffusion) { + std::string nda_dependency_error{ "Error building framework for Drift Diffusion: Required dependency missing: "}; + AssertThrow(parameters.nda_data_.angular_flux_integrator_ptr_ != nullptr, + dealii::ExcMessage(nda_dependency_error + "angular flux integrator ptr is null")) + AssertThrow(parameters.nda_data_.higher_order_moments_ptr_ != nullptr, + dealii::ExcMessage(nda_dependency_error + "higher order moments ptr is null")) + } + // Build instruments to be used auto color_string_instrument_ptr = Shared( InstrumentBuilder::BuildInstrument(InstrumentName::kColorStatusToConditionalOstream)); @@ -106,6 +117,7 @@ auto FrameworkHelper::BuildFramework( InstrumentBuilder::BuildInstrument(InstrumentName::kConvergenceStatusToConditionalOstream)); auto string_instrument_ptr = Shared( InstrumentBuilder::BuildInstrument(InstrumentName::kStringToConditionalOstream)); + builder.set_color_status_instrument_ptr(color_string_instrument_ptr); builder.set_convergence_status_instrument_ptr(convergence_status_instrument_ptr); builder.set_status_instrument_ptr(string_instrument_ptr); @@ -143,7 +155,11 @@ auto FrameworkHelper::BuildFramework( // Set up for Angular/Scalar solve - if (parameters.equation_type != problem::EquationType::kDiffusion) { + using EquationType = problem::EquationType; + std::set scalar_types{EquationType::kDiffusion, EquationType::kDriftDiffusion}; + std::set angular_types{EquationType::kSelfAdjointAngularFlux}; + + if (angular_types.contains(parameters.equation_type)) { // Angular solve AssertThrow(parameters.angular_quadrature_order.has_value(), dealii::ExcMessage("Error building framework, equation type requires quadrature but order is null")) @@ -190,14 +206,30 @@ auto FrameworkHelper::BuildFramework( builder.BuildStamper(domain_ptr), quadrature_set_ptr); } - } else if (parameters.equation_type == problem::EquationType::kDiffusion) { + } else if (parameters.equation_type == EquationType::kDiffusion || + parameters.equation_type == EquationType::kDriftDiffusion) { auto diffusion_formulation_ptr = builder.BuildDiffusionFormulation(finite_element_ptr, parameters.cross_sections_.value(), formulation::DiffusionFormulationImpl::kDefault); diffusion_formulation_ptr->Precalculate(domain_ptr->Cells().at(0)); - updater_pointers = builder.BuildUpdaterPointers(std::move(diffusion_formulation_ptr), - builder.BuildStamper(domain_ptr), - reflective_boundaries); + if (parameters.equation_type == EquationType::kDriftDiffusion) { + auto drift_diffusion_formulation_ptr = builder.BuildDriftDiffusionFormulation( + parameters.nda_data_.angular_flux_integrator_ptr_, + finite_element_ptr, + parameters.cross_sections_.value()); + updater_pointers = builder.BuildUpdaterPointers( + std::move(diffusion_formulation_ptr), + std::move(drift_diffusion_formulation_ptr), + builder.BuildStamper(domain_ptr), + parameters.nda_data_.angular_flux_integrator_ptr_, + parameters.nda_data_.higher_order_moments_ptr_, + parameters.nda_data_.higher_order_angular_flux_, + reflective_boundaries); + } else { + updater_pointers = builder.BuildUpdaterPointers(std::move(diffusion_formulation_ptr), + builder.BuildStamper(domain_ptr), + reflective_boundaries); + } } auto initializer_ptr = builder.BuildInitializer(updater_pointers.fixed_updater_ptr, @@ -220,6 +252,35 @@ auto FrameworkHelper::BuildFramework( validator.AddPart(FrameworkPart::AngularSolutionStorage); } + auto system_ptr = builder.BuildSystem(parameters.neutron_energy_groups, + n_angles, + *domain_ptr, + group_solution_ptr->GetSolution(0).size(), + parameters.eigen_solver_type.has_value(), + need_angular_solution_storage); + + std::unique_ptr post_processing_subroutine{ nullptr }; + // For NDA we need to build a sub-routine framework to run the NDA process + if (parameters.use_nda_) { + auto nda_parameters{ parameters }; + nda_parameters.name = "NDA Drift-Diffusion"; + nda_parameters.use_nda_ = false; + nda_parameters.framework_level_ = 1; + nda_parameters.output_filename_base = parameters.output_filename_base + "_nda"; + nda_parameters.nda_data_.angular_flux_integrator_ptr_ = + Shared(builder.BuildAngularFluxIntegrator(quadrature_set_ptr)); + nda_parameters.nda_data_.higher_order_moments_ptr_ = system_ptr->current_moments; + nda_parameters.nda_data_.higher_order_angular_flux_ = angular_solutions_; + std::unique_ptr subroutine_framework_ptr{ nullptr }; + if (subroutine_framework_helper_ptr_ != nullptr) { + subroutine_framework_ptr = std::move(subroutine_framework_helper_ptr_->BuildFramework(builder, nda_parameters)); + } else { + subroutine_framework_ptr = std::move(BuildFramework(builder, nda_parameters)); + } + post_processing_subroutine = builder.BuildSubroutine(std::move(subroutine_framework_ptr), + iteration::subroutine::SubroutineName::kGetScalarFluxFromFramework); + } + std::unique_ptr outer_iteration_ptr{ nullptr }; if (parameters.eigen_solver_type.has_value()){ @@ -244,12 +305,10 @@ auto FrameworkHelper::BuildFramework( parameters.output_filename_base); } - auto system_ptr = builder.BuildSystem(parameters.neutron_energy_groups, - n_angles, - *domain_ptr, - group_solution_ptr->GetSolution(0).size(), - parameters.eigen_solver_type.has_value(), - need_angular_solution_storage); + // Add subroutines if applicable + if (post_processing_subroutine != nullptr) { + outer_iteration_ptr->AddPostIterationSubroutine(std::move(post_processing_subroutine)); + } validator.ReportValidation(); @@ -262,7 +321,7 @@ auto FrameworkHelper::BuildFramework( template auto FrameworkHelper::BuildFramework( builder::FrameworkBuilderI& builder, - const FrameworkParameters& parameters, + FrameworkParameters& parameters, system::moments::SphericalHarmonicI* previous_solution_ptr) -> std::unique_ptr { auto framework_ptr = BuildFramework(builder, parameters); auto dynamic_framework_ptr = dynamic_cast(framework_ptr.get()); diff --git a/src/framework/framework_helper.hpp b/src/framework/framework_helper.hpp index fa5a99e27..0678d9abe 100644 --- a/src/framework/framework_helper.hpp +++ b/src/framework/framework_helper.hpp @@ -1,6 +1,7 @@ #ifndef BART_SRC_FRAMEWORK_FRAMEWORK_HELPER_HPP_ #define BART_SRC_FRAMEWORK_FRAMEWORK_HELPER_HPP_ +#include "framework/framework_helper_i.hpp" #include "problem/parameters_i.h" #include "framework/builder/framework_builder_i.hpp" #include "material/material_protobuf.h" @@ -10,21 +11,26 @@ namespace bart::framework { template -class FrameworkHelper { +class FrameworkHelper : public FrameworkHelperI { public: using SystemHelper = const system::SystemHelperI; FrameworkHelper(const std::shared_ptr& system_helper_ptr); - [[nodiscard]] auto ToFrameworkParameters(const problem::ParametersI& parameters) -> framework::FrameworkParameters; + [[nodiscard]] auto ToFrameworkParameters(const problem::ParametersI& parameters) -> framework::FrameworkParameters override; [[nodiscard]] auto BuildFramework(builder::FrameworkBuilderI&, - const framework::FrameworkParameters&) -> std::unique_ptr; + framework::FrameworkParameters&) -> std::unique_ptr override; [[nodiscard]] auto BuildFramework(builder::FrameworkBuilderI&, - const framework::FrameworkParameters&, - system::moments::SphericalHarmonicI*) -> std::unique_ptr; + framework::FrameworkParameters&, + system::moments::SphericalHarmonicI*) -> std::unique_ptr override; + auto SetSubroutineFrameworkHelper(std::unique_ptr> framework_helper_ptr) { + subroutine_framework_helper_ptr_ = std::move(framework_helper_ptr); } auto system_helper_ptr() { return system_helper_ptr_.get(); } + auto subroutine_framework_helper_ptr() { return subroutine_framework_helper_ptr_.get(); } private: std::shared_ptr system_helper_ptr_{ nullptr }; + // Subroune framework helper, helps build frameworks for subroutines, used only for testing + std::unique_ptr> subroutine_framework_helper_ptr_{ nullptr }; }; } // namespace bart::framework diff --git a/src/framework/framework_helper_i.hpp b/src/framework/framework_helper_i.hpp new file mode 100644 index 000000000..1ead48b98 --- /dev/null +++ b/src/framework/framework_helper_i.hpp @@ -0,0 +1,27 @@ +#ifndef BART_SRC_FRAMEWORK_FRAMEWORK_HELPER_I_HPP_ +#define BART_SRC_FRAMEWORK_FRAMEWORK_HELPER_I_HPP_ + +#include "problem/parameters_i.h" +#include "framework/builder/framework_builder_i.hpp" +#include "material/material_protobuf.h" +#include "system/system_helper_i.hpp" +#include "system/moments/spherical_harmonic_i.h" + +namespace bart::framework { + +template +class FrameworkHelperI { + public: + virtual ~FrameworkHelperI() = default; + virtual auto ToFrameworkParameters(const problem::ParametersI& parameters) -> framework::FrameworkParameters = 0; + virtual auto BuildFramework(builder::FrameworkBuilderI&, + framework::FrameworkParameters&) -> std::unique_ptr = 0; + virtual auto BuildFramework(builder::FrameworkBuilderI&, + framework::FrameworkParameters&, + system::moments::SphericalHarmonicI*) -> std::unique_ptr = 0; +}; + + +} // namespace bart::framework + +#endif //BART_SRC_FRAMEWORK_FRAMEWORK_HELPER_I_HPP_ diff --git a/src/framework/framework_parameters.hpp b/src/framework/framework_parameters.hpp index 629dd93a8..d3d2f77e3 100644 --- a/src/framework/framework_parameters.hpp +++ b/src/framework/framework_parameters.hpp @@ -2,10 +2,13 @@ #define BART_SRC_FRAMEWORK_FRAMEWORK_PARAMETERS_HPP_ #include "eigenvalue/k_effective/factory.hpp" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include "data/cross_sections.h" #include "utility/named_type.h" +#include "quadrature/calculators/angular_flux_integrator_i.hpp" #include "quadrature/quadrature_set_i.h" +#include "system/moments/spherical_harmonic_i.h" +#include "system/solution/solution_types.h" #include #include @@ -14,12 +17,15 @@ namespace bart::framework { struct FrameworkParameters { + using AngularFluxIntegrator = quadrature::calculators::AngularFluxIntegratorI; + using AngularFluxStorage = system::solution::EnergyGroupToAngularSolutionPtrMap; using AngularQuadratureOrder = quadrature::Order; using DomainSize = utility::NamedType, struct DomainSizeStruct>; using K_EffectiveUpdaterName = eigenvalue::k_effective::K_EffectiveUpdaterName; using NumberOfCells = utility::NamedType, struct NumberOfCellsStruct>; using PolynomialDegree = utility::NamedType; using SpatialDimension = utility::NamedType; + using Moments = system::moments::SphericalHarmonicI; std::string name{""}; std::string output_filename_base{""}; @@ -53,9 +59,22 @@ struct FrameworkParameters { PolynomialDegree polynomial_degree{ 2 }; + // Optional shared framework parts template using OptionalSharedPart = std::optional>; OptionalSharedPart cross_sections_ { std::nullopt }; + + // Acceleration methods + bool use_nda_{ false }; + // Indicates "level" of the framework, with 0 being the top level + int framework_level_{ 0 }; + // Higher order data to support NDA + struct NDA_Data { + std::shared_ptr angular_flux_integrator_ptr_{ nullptr }; + std::shared_ptr higher_order_moments_ptr_{ nullptr }; + AngularFluxStorage higher_order_angular_flux_{}; + }; + NDA_Data nda_data_{}; }; } // namespace bart::framework diff --git a/src/framework/tests/framework_helper_build_framework_test.cpp b/src/framework/tests/framework_helper_build_framework_test.cpp index 2b7be30f8..4bc37f13e 100644 --- a/src/framework/tests/framework_helper_build_framework_test.cpp +++ b/src/framework/tests/framework_helper_build_framework_test.cpp @@ -1,6 +1,7 @@ #include #include "framework/framework_helper.hpp" +#include "quadrature/calculators/tests/angular_flux_integrator_mock.hpp" #include "convergence/tests/final_checker_mock.h" #include "eigenvalue/k_effective/tests/k_effective_updater_mock.h" #include "formulation/tests/stamper_mock.h" @@ -10,14 +11,18 @@ #include "formulation/updater/tests/fixed_updater_mock.h" #include "formulation/updater/tests/scattering_source_updater_mock.h" #include "formulation/scalar/tests/diffusion_mock.h" +#include "formulation/scalar/tests/drift_diffusion_mock.hpp" #include "framework/builder/framework_builder_i.hpp" #include "framework/builder/tests/framework_builder_mock.hpp" #include "framework/builder/tests/framework_validator_mock.hpp" #include "framework/framework_parameters.hpp" #include "framework/framework.hpp" +#include "framework/tests/framework_helper_mock.hpp" +#include "framework/tests/framework_mock.hpp" #include "iteration/initializer/tests/initializer_mock.h" #include "iteration/group/tests/group_solve_iteration_mock.h" #include "iteration/outer/tests/outer_iteration_mock.hpp" +#include "iteration/subroutine/tests/subroutine_mock.hpp" #include "domain/finite_element/tests/finite_element_mock.h" #include "domain/tests/definition_mock.h" #include "material/tests/mock_material.h" @@ -28,6 +33,8 @@ #include "solver/group/tests/single_group_solver_mock.h" #include "system/tests/system_helper_mock.hpp" #include "system/solution/tests/mpi_group_angular_solution_mock.h" +#include "system/solution/solution_types.h" +#include "system/moments/tests/spherical_harmonic_mock.h" #include "system/moments/spherical_harmonic_types.h" #include "system/system.hpp" @@ -47,10 +54,14 @@ class FrameworkHelperBuildFrameworkIntegrationTests : public ::testing::Test { public: static constexpr int dim = DimensionWrapper::value; // Mock types + using AngularFluxIntegratorMock = quadrature::calculators::AngularFluxIntegratorMock; using DiffusionFormulationMock = typename formulation::scalar::DiffusionMock; using DomainMock = typename domain::DefinitionMock; + using DriftDiffusionFormulationMock = typename formulation::scalar::DriftDiffusionMock; using FiniteElementMock = typename domain::finite_element::FiniteElementMock; using FrameworkBuidler = framework::builder::FrameworkBuilderMock; + using FrameworkMock = framework::FrameworkMock; + using FrameworkHelperMock = NiceMock>; using FrameworkParameters = framework::FrameworkParameters; using GroupSolutionMock = system::solution::MPIGroupAngularSolutionMock; using GroupSolveIterationMock = iteration::group::GroupSolveIterationMock; @@ -65,11 +76,12 @@ class FrameworkHelperBuildFrameworkIntegrationTests : public ::testing::Test { using StamperMock = typename formulation::StamperMock; using SAAFFormulationMock = typename formulation::angular::SelfAdjointAngularFluxMock; using SingleGroupSolverMock = solver::group::SingleGroupSolverMock; + using SubroutineMock = iteration::subroutine::SubroutineMock; using SystemHelper = typename system::SystemHelperMock; using System = system::System; using Validator = framework::builder::FrameworkValidatorMock; - using UpdaterPointers = FrameworkBuidler::UpdaterPointers; + using UpdaterPointers = typename FrameworkBuidler::UpdaterPointers; using BoundaryConditionsUpdaterMock = formulation::updater::BoundaryConditionsUpdaterMock; using FissionSourceUpdaterMock = formulation::updater::FissionSourceUpdaterMock; using FixedTermUpdaterMock = formulation::updater::FixedUpdaterMock; @@ -80,9 +92,13 @@ class FrameworkHelperBuildFrameworkIntegrationTests : public ::testing::Test { std::unique_ptr test_helper_ptr_; // Mock pointers and observation pointers + AngularFluxIntegratorMock* angular_flux_integrator_obs_ptr_{ nullptr }; DiffusionFormulationMock* diffusion_formulation_obs_ptr_{ nullptr }; DomainMock* domain_obs_ptr_{ nullptr }; + DriftDiffusionFormulationMock* drift_diffusion_formulation_obs_ptr_{ nullptr }; FiniteElementMock* finite_element_obs_ptr_{ nullptr }; + FrameworkHelperMock* subroutine_framework_helper_obs_ptr_{ nullptr }; + FrameworkMock* subroutine_framework_obs_ptr_{ nullptr }; GroupSolutionMock* group_solution_obs_ptr_{ nullptr }; GroupSolveIterationMock* group_solve_iteration_obs_ptr{ nullptr }; InitializerMock* initializer_obs_ptr_{ nullptr }; @@ -98,6 +114,7 @@ class FrameworkHelperBuildFrameworkIntegrationTests : public ::testing::Test { SAAFFormulationMock* saaf_formulation_obs_ptr_{ nullptr }; SingleGroupSolverMock* single_group_solver_obs_ptr_{ nullptr }; StamperMock* stamper_obs_ptr_{ nullptr }; + SubroutineMock* subroutine_obs_ptr_{ nullptr }; std::shared_ptr system_helper_mock_ptr_{ nullptr }; System* system_obs_ptr_{ nullptr }; @@ -111,7 +128,8 @@ class FrameworkHelperBuildFrameworkIntegrationTests : public ::testing::Test { system::MPIVector solution_; Validator mock_validator_; - auto RunTest(const FrameworkParameters& parameters) -> void; + auto SetExpectations(FrameworkParameters& parameters) -> void; + auto RunTest(FrameworkParameters& parameters) -> void; auto SetUp() -> void override; }; @@ -132,6 +150,7 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> default_parameters_.material_mapping = "1 1"; default_parameters_.domain_size = DomainSize(test_helpers::RandomVector(dim, 0, 100)); default_parameters_.uniform_refinements = test_helpers::RandomInt(1, 4); + default_parameters_.use_nda_ = false; auto random_n_cells_double = test_helpers::RandomVector(dim, 10, 20); std::vector random_n_cells(random_n_cells_double.cbegin(), random_n_cells_double.cend()); @@ -143,12 +162,20 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> } // Mocks and observation pointers + auto angular_flux_integrator_ptr = std::make_unique(); + angular_flux_integrator_obs_ptr_ = angular_flux_integrator_ptr.get(); auto diffusion_formulation_ptr = std::make_unique>(); diffusion_formulation_obs_ptr_ = diffusion_formulation_ptr.get(); auto domain_ptr = std::make_unique>(); domain_obs_ptr_ = domain_ptr.get(); + auto drift_diffusion_formulation_ptr = std::make_unique>(); + drift_diffusion_formulation_obs_ptr_ = drift_diffusion_formulation_ptr.get(); auto finite_element_ptr = std::make_unique>(); finite_element_obs_ptr_ = finite_element_ptr.get(); + auto subroutine_framework_ptr = std::make_unique(); + subroutine_framework_obs_ptr_ = subroutine_framework_ptr.get(); + auto subroutine_framework_helper = std::make_unique(); + subroutine_framework_helper_obs_ptr_ = subroutine_framework_helper.get(); auto group_solution_ptr = std::make_unique>(); group_solution_obs_ptr_ = group_solution_ptr.get(); auto group_solve_iteration_ptr = std::make_unique>(); @@ -178,6 +205,8 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> single_group_solver_obs_ptr_ = single_group_solver_ptr.get(); auto stamper_ptr = std::make_unique>(); stamper_obs_ptr_ = stamper_ptr.get(); + auto subroutine_ptr = std::make_unique>(); + subroutine_obs_ptr_ = subroutine_ptr.get(); system_helper_mock_ptr_ = std::make_shared>(); auto system_ptr = std::make_unique(); system_obs_ptr_ = system_ptr.get(); @@ -190,11 +219,17 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> ON_CALL(*group_solution_obs_ptr_, GetSolution(_)).WillByDefault(ReturnRef(solution_)); + ON_CALL(*subroutine_framework_helper_obs_ptr_, BuildFramework(_,_)).WillByDefault(ReturnByMove(subroutine_framework_ptr)); + using DiffusionFormulationPtr = std::unique_ptr; + using DriftDiffusionFormulationPtr = std::unique_ptr; using SAAFFormulationPtr = std::unique_ptr; + ON_CALL(mock_builder_, BuildAngularFluxIntegrator(_)).WillByDefault(ReturnByMove(angular_flux_integrator_ptr)); ON_CALL(mock_builder_, BuildDiffusionFormulation(_,_,_)).WillByDefault(ReturnByMove(diffusion_formulation_ptr)); ON_CALL(mock_builder_, BuildDomain(_, _, _, _)).WillByDefault(ReturnByMove(domain_ptr)); + ON_CALL(mock_builder_, BuildDriftDiffusionFormulation(_, _, _)) + .WillByDefault(ReturnByMove(drift_diffusion_formulation_ptr)); ON_CALL(mock_builder_, BuildFiniteElement(_,_,_)).WillByDefault(ReturnByMove(finite_element_ptr)); ON_CALL(mock_builder_, BuildGroupSolution(_)).WillByDefault(ReturnByMove(group_solution_ptr)); ON_CALL(mock_builder_, BuildGroupSolveIteration(_,_,_,_,_,_)).WillByDefault(ReturnByMove(group_solve_iteration_ptr)); @@ -214,8 +249,11 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> ON_CALL(mock_builder_, BuildSAAFFormulation(_,_,_,_)).WillByDefault(ReturnByMove(saaf_ptr)); ON_CALL(mock_builder_, BuildSingleGroupSolver(_,_)).WillByDefault(ReturnByMove(single_group_solver_ptr)); ON_CALL(mock_builder_, BuildStamper(_)).WillByDefault(ReturnByMove(stamper_ptr)); + ON_CALL(mock_builder_, BuildSubroutine(_,_)).WillByDefault(ReturnByMove(subroutine_ptr)); ON_CALL(mock_builder_, BuildUpdaterPointers(A(),_,_)).WillByDefault(Return(updater_pointers_)); ON_CALL(mock_builder_, BuildUpdaterPointers(A(),_,_)).WillByDefault(Return(updater_pointers_)); + ON_CALL(mock_builder_, BuildUpdaterPointers(A(), A(),_,_,_,_,_)) + .WillByDefault(Return(updater_pointers_)); ON_CALL(mock_builder_, BuildUpdaterPointers(_,_,_,_,_)).WillByDefault(Return(updater_pointers_)); ON_CALL(mock_builder_, BuildSystem(_,_,_,_,_,_)).WillByDefault(ReturnByMove(system_ptr)); ON_CALL(mock_builder_, set_color_status_instrument_ptr(_)).WillByDefault(ReturnRef(mock_builder_)); @@ -233,11 +271,12 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::SetUp() -> ON_CALL(*quadrature_set_mock_ptr_, size()).WillByDefault(Return(this->total_quadrature_angles)); test_helper_ptr_ = std::make_unique(system_helper_mock_ptr_); + test_helper_ptr_->SetSubroutineFrameworkHelper(std::move(subroutine_framework_helper)); } template -auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( - const FrameworkParameters ¶meters) -> void { +auto FrameworkHelperBuildFrameworkIntegrationTests::SetExpectations( + FrameworkParameters ¶meters) -> void { auto& mock_builder = this->mock_builder_; int n_angles{ 1 }; bool need_angular_storage{ false }; @@ -246,7 +285,6 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( EXPECT_CALL(mock_builder, validator_ptr()).Times(AtLeast(1)).WillRepeatedly(DoDefault()); EXPECT_CALL(mock_validator_, Parse(A())); - // Mock Builder calls EXPECT_CALL(mock_builder, set_color_status_instrument_ptr(NotNull())).WillOnce(DoDefault()); EXPECT_CALL(mock_builder, set_convergence_status_instrument_ptr(NotNull())).WillOnce(DoDefault()); @@ -301,6 +339,15 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( formulation::SAAFFormulationImpl::kDefault)) .WillOnce(DoDefault()); EXPECT_CALL(*saaf_formulation_obs_ptr_, Initialize(cells_.at(0))); + + if (parameters.use_nda_ || !parameters.reflective_boundaries.empty()) { + need_angular_storage = true; + EXPECT_CALL(*system_helper_mock_ptr_, SetUpEnergyGroupToAngularSolutionPtrMap( + _, parameters.neutron_energy_groups, total_quadrature_angles)); + EXPECT_CALL(*group_solve_iteration_obs_ptr, UpdateThisAngularSolutionMap(_)).WillOnce(DoDefault()); + } + + // Determine if angular flux storage is required if (parameters.reflective_boundaries.empty()) { using SAAFFormulationPtr = std::unique_ptr::SAAFFormulation>; EXPECT_CALL(mock_builder, BuildUpdaterPointers( @@ -309,10 +356,6 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( Pointee(Ref(*quadrature_set_mock_ptr_)))) .WillOnce(DoDefault()); } else { - // Should have angular storage - need_angular_storage = true; - EXPECT_CALL(*system_helper_mock_ptr_, SetUpEnergyGroupToAngularSolutionPtrMap( - _, parameters.neutron_energy_groups, total_quadrature_angles)); EXPECT_CALL(mock_builder, BuildUpdaterPointers( Pointee(Ref(*saaf_formulation_obs_ptr_)), Pointee(Ref(*stamper_obs_ptr_)), @@ -320,8 +363,8 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( ContainerEq(reflective_boundaries), _)) .WillOnce(DoDefault()); - EXPECT_CALL(*group_solve_iteration_obs_ptr, UpdateThisAngularSolutionMap(_)).WillOnce(DoDefault()); } + } else if (parameters.equation_type == problem::EquationType::kDiffusion) { EXPECT_CALL(mock_builder, BuildDiffusionFormulation(Pointee(Ref(*finite_element_obs_ptr_)), Pointee(Ref(*parameters.cross_sections_.value())), @@ -331,6 +374,20 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( EXPECT_CALL(mock_builder, BuildUpdaterPointers(A(), Pointee(Ref(*stamper_obs_ptr_)), ContainerEq(reflective_boundaries))).WillOnce(DoDefault()); + } else if (parameters.equation_type == problem::EquationType::kDriftDiffusion) { + EXPECT_CALL(mock_builder, BuildDriftDiffusionFormulation( + Pointee(Ref(*parameters.nda_data_.angular_flux_integrator_ptr_)), + Pointee(Ref(*finite_element_obs_ptr_)), + Pointee(Ref(*parameters.cross_sections_.value())))).WillOnce(DoDefault()); + EXPECT_CALL(mock_builder, BuildDiffusionFormulation(Pointee(Ref(*finite_element_obs_ptr_)), + Pointee(Ref(*parameters.cross_sections_.value())), + _)).WillOnce(DoDefault()); + EXPECT_CALL(*diffusion_formulation_obs_ptr_, Precalculate(cells_.at(0))); + using DiffusionFormulationPtr = std::unique_ptr::DiffusionFormulation>; + using DriftDiffusionFormulationPtr = std::unique_ptr::DriftDiffusionFormulation>; + EXPECT_CALL(mock_builder, BuildUpdaterPointers(A(), + A(), + Pointee(Ref(*stamper_obs_ptr_)), _, _, _, _)).WillOnce(DoDefault()); } // End formulation specific calls, need_angular_storage should be set properly now @@ -396,6 +453,22 @@ auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( is_eigenvalue_solve, need_angular_storage)).WillOnce(DoDefault()); + if (parameters.use_nda_) { + EXPECT_CALL(mock_builder, BuildAngularFluxIntegrator(Pointee(Ref(*quadrature_set_mock_ptr_)))).WillOnce(DoDefault()); + EXPECT_CALL(*subroutine_framework_helper_obs_ptr_, BuildFramework(Ref(mock_builder), _)).WillOnce(DoDefault()); + EXPECT_CALL(mock_builder, BuildSubroutine(Pointee(Ref(*subroutine_framework_obs_ptr_)), + iteration::subroutine::SubroutineName::kGetScalarFluxFromFramework)) + .WillOnce(DoDefault()); + EXPECT_CALL(*outer_iteration_eigensolve_obs_ptr_, AddPostIterationSubroutine(Pointee(Ref(*subroutine_obs_ptr_)))) + .WillOnce(ReturnRef(*outer_iteration_eigensolve_obs_ptr_)); + } +} + +template +auto FrameworkHelperBuildFrameworkIntegrationTests::RunTest( + FrameworkParameters ¶meters) -> void { + SetExpectations(parameters); + const bool is_eigenvalue_solve {parameters.eigen_solver_type.has_value() }; using ExpectedType = framework::Framework; auto framework_ptr = test_helper_ptr_->BuildFramework(this->mock_builder_, parameters); ASSERT_NE(framework_ptr, nullptr); @@ -427,6 +500,41 @@ TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkDiffusio this->RunTest(parameters); } +TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildDriftDiffusion) { + auto parameters{ this->default_parameters_ }; + parameters.eigen_solver_type = problem::EigenSolverType::kPowerIteration; + parameters.equation_type = problem::EquationType::kDriftDiffusion; + parameters.nda_data_.angular_flux_integrator_ptr_ = std::make_shared(); + parameters.nda_data_.higher_order_moments_ptr_ = std::make_shared(); + parameters.nda_data_.higher_order_angular_flux_[{system::EnergyGroup(0), system::AngleIdx(0)}] = + std::make_shared>(3); + this->RunTest(parameters); +} + +TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildDriftDiffusionNoAngularFluxIntegrator) { + auto parameters{ this->default_parameters_ }; + parameters.equation_type = problem::EquationType::kDriftDiffusion; + parameters.eigen_solver_type = problem::EigenSolverType::kPowerIteration; + parameters.nda_data_.higher_order_moments_ptr_ = std::make_shared(); + parameters.nda_data_.higher_order_angular_flux_[{system::EnergyGroup(0), system::AngleIdx(0)}] = + std::make_shared>(3); + EXPECT_ANY_THROW({ + [[maybe_unused]] auto framework = this->test_helper_ptr_->BuildFramework(this->mock_builder_, parameters); + }); +} + +TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildDriftDiffusionNoHigherOrderMoments) { + auto parameters{ this->default_parameters_ }; + parameters.equation_type = problem::EquationType::kDriftDiffusion; + parameters.eigen_solver_type = problem::EigenSolverType::kPowerIteration; + parameters.nda_data_.angular_flux_integrator_ptr_ = std::make_shared(); + parameters.nda_data_.higher_order_angular_flux_[{system::EnergyGroup(0), system::AngleIdx(0)}] = + std::make_shared>(3); + EXPECT_ANY_THROW({ + [[maybe_unused]] auto framework = this->test_helper_ptr_->BuildFramework(this->mock_builder_, parameters); + }); +} + TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkSAAF) { auto parameters{ this-> default_parameters_ }; using Order = framework::FrameworkParameters::AngularQuadratureOrder; @@ -457,6 +565,18 @@ TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkSAAFEige this->RunTest(parameters); } +TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkSAAFEigensolveWithNDA) { + auto parameters{ this-> default_parameters_ }; + using Order = framework::FrameworkParameters::AngularQuadratureOrder; + parameters.equation_type = problem::EquationType::kSelfAdjointAngularFlux; + parameters.angular_quadrature_type = problem::AngularQuadType::kLevelSymmetricGaussian; + parameters.angular_quadrature_order = Order(test_helpers::RandomInt(5, 10)); + parameters.eigen_solver_type = problem::EigenSolverType::kPowerIteration; + parameters.use_nda_ = true; + + this->RunTest(parameters); +} + TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkSAAFReflectiveBCs) { auto parameters{ this-> default_parameters_ }; using Order = framework::FrameworkParameters::AngularQuadratureOrder; @@ -478,4 +598,6 @@ TYPED_TEST(FrameworkHelperBuildFrameworkIntegrationTests, BuildFrameworkSAAFRefl this->RunTest(parameters); } + + } // namespace diff --git a/src/framework/tests/framework_helper_constructor_test.cpp b/src/framework/tests/framework_helper_constructor_test.cpp index 97ce917ad..27820a142 100644 --- a/src/framework/tests/framework_helper_constructor_test.cpp +++ b/src/framework/tests/framework_helper_constructor_test.cpp @@ -1,4 +1,5 @@ #include "framework/framework_helper.hpp" +#include "framework/tests/framework_helper_mock.hpp" #include "system/tests/system_helper_mock.hpp" #include "test_helpers/gmock_wrapper.h" @@ -32,4 +33,15 @@ TYPED_TEST(FrameworkHelperConstructorTests, ConstructorNullDependency) { } +TYPED_TEST(FrameworkHelperConstructorTests, SetSubrountineFrameworkHelper) { + constexpr int dim = this->dim; + using SystemHelper = const system::SystemHelperMock; + auto system_helper_ptr = std::make_shared(); + framework::FrameworkHelper helper(system_helper_ptr); + EXPECT_THAT(helper.system_helper_ptr(), WhenDynamicCastTo(NotNull())); + EXPECT_EQ(helper.subroutine_framework_helper_ptr(), nullptr); + helper.SetSubroutineFrameworkHelper(std::make_unique>()); + EXPECT_NE(helper.subroutine_framework_helper_ptr(), nullptr); +} + } // namespace diff --git a/src/framework/tests/framework_helper_mock.hpp b/src/framework/tests/framework_helper_mock.hpp new file mode 100644 index 000000000..189799772 --- /dev/null +++ b/src/framework/tests/framework_helper_mock.hpp @@ -0,0 +1,21 @@ +#ifndef BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_HELPER_MOCK_HPP_ +#define BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_HELPER_MOCK_HPP_ + +#include "framework/framework_helper_i.hpp" +#include "test_helpers/gmock_wrapper.h" + +namespace bart::framework { + +template +class FrameworkHelperMock : public FrameworkHelperI { + public: + MOCK_METHOD(framework::FrameworkParameters, ToFrameworkParameters, (const problem::ParametersI& parameters), (override)); + MOCK_METHOD(std::unique_ptr, BuildFramework, (builder::FrameworkBuilderI&, + framework::FrameworkParameters&), (override)); + MOCK_METHOD(std::unique_ptr, BuildFramework, (builder::FrameworkBuilderI&, + framework::FrameworkParameters&, system::moments::SphericalHarmonicI*), (override)); +}; + +} // namespace bart::framework + +#endif //BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_HELPER_MOCK_HPP_ diff --git a/src/framework/tests/framework_helper_to_framework_parameters_test.cpp b/src/framework/tests/framework_helper_to_framework_parameters_test.cpp index 0761a9c17..af0c4143a 100644 --- a/src/framework/tests/framework_helper_to_framework_parameters_test.cpp +++ b/src/framework/tests/framework_helper_to_framework_parameters_test.cpp @@ -31,6 +31,7 @@ class FrameworkHelperToFrameworkParametersTest : public ::testing::Test { const std::unordered_map material_filenames_{ {0, "test_data/material/serialized/uo2_20.material"}}; const int energy_groups_{ 7 }; // required by the material file + const bool use_nda_{ false }; auto SetExpectations(const framework::FrameworkParameters&, const std::string& material_mapping_filename) -> void; auto SetExpectations(const framework::FrameworkParameters&) -> void; @@ -64,6 +65,7 @@ auto FrameworkHelperToFrameworkParametersTest::SetUp() -> void { default_parameters_.cell_finite_element_type = problem::CellFiniteElementType::kGaussian; using PolynomialDegree = framework::FrameworkParameters::PolynomialDegree; default_parameters_.polynomial_degree = PolynomialDegree(test_helpers::RandomInt(2, 5)); + default_parameters_.use_nda_ = use_nda_; test_helper_ptr_ = std::make_unique(std::make_unique()); system_helper_obs_ptr_ = dynamic_cast(test_helper_ptr_->system_helper_ptr()); @@ -105,6 +107,7 @@ auto FrameworkHelperToFrameworkParametersTest::SetExpectations( EXPECT_CALL(parameters_mock_, MaterialFilenames()).WillOnce(Return(material_filenames_)); EXPECT_CALL(parameters_mock_, NumberOfMaterials()).WillOnce(Return(static_cast(material_filenames_.size()))); EXPECT_CALL(parameters_mock_, K_EffectiveUpdaterType()).WillOnce(Return(parameters.k_effective_updater)); + EXPECT_CALL(parameters_mock_, DoNDA()).WillOnce(Return(parameters.use_nda_)); } AssertionResult AreEqual(const framework::FrameworkParameters& lhs, const framework::FrameworkParameters& rhs) { @@ -144,6 +147,8 @@ AssertionResult AreEqual(const framework::FrameworkParameters& lhs, const framew return AssertionFailure() << "polynomial degree do not match"; } else if (lhs.k_effective_updater != rhs.k_effective_updater) { return AssertionFailure() << "K-effective updaters do not match"; + } else if (lhs.use_nda_ != rhs.use_nda_) { + return AssertionFailure() << "use NDA flag do not match"; } return AssertionSuccess(); } @@ -159,6 +164,14 @@ TEST_F(FrameworkHelperToFrameworkParametersTest, DefaultParameters) { EXPECT_NE(returned_parameters.cross_sections_.value(), nullptr); } +TEST_F(FrameworkHelperToFrameworkParametersTest, UseNDATrue) { + auto test_parameters{ default_parameters_ }; + test_parameters.use_nda_ = true; + SetExpectations(test_parameters); + auto returned_parameters = test_helper_ptr_->ToFrameworkParameters(parameters_mock_); + EXPECT_TRUE(AreEqual(returned_parameters, test_parameters)); +} + TEST_F(FrameworkHelperToFrameworkParametersTest, SAAFWithLevelSymmetric) { auto test_parameters{ default_parameters_ }; test_parameters.equation_type = problem::EquationType::kSelfAdjointAngularFlux; @@ -230,6 +243,8 @@ TEST_F(FrameworkHelperToFrameworkParametersTest, BadMaterialMapping) { reflective_boundaries.at(boundary) = true; EXPECT_CALL(parameters_mock_, ReflectiveBoundary()).WillOnce(Return(reflective_boundaries)); EXPECT_CALL(parameters_mock_, MaterialMapFilename()).WillOnce(Return("bad_material_file")); + EXPECT_CALL(parameters_mock_, K_EffectiveUpdaterType()).WillOnce(Return(test_parameters.k_effective_updater)); + EXPECT_CALL(parameters_mock_, DoNDA()).WillOnce(Return(test_parameters.use_nda_)); EXPECT_ANY_THROW({ auto returned_parameters = test_helper_ptr_->ToFrameworkParameters(parameters_mock_); diff --git a/src/iteration/initializer/factory.hpp b/src/iteration/initializer/factory.hpp new file mode 100644 index 000000000..c94723221 --- /dev/null +++ b/src/iteration/initializer/factory.hpp @@ -0,0 +1,13 @@ +#ifndef BART_SRC_ITERATION_INITIALIZER_FACTORY_HPP_ +#define BART_SRC_ITERATION_INITIALIZER_FACTORY_HPP_ + +namespace bart::iteration::initializer { + +enum class InitializerName { + kInitializeFixedTermsOnce = 0, + kInitializeFixedTermsAndResetMoments = 1, +}; + +} // namespace bart::iteration::initializer + +#endif //BART_SRC_ITERATION_INITIALIZER_FACTORY_HPP_ diff --git a/src/iteration/initializer/initialize_fixed_terms_reset_moments.hpp b/src/iteration/initializer/initialize_fixed_terms_reset_moments.hpp new file mode 100644 index 000000000..fed52ff31 --- /dev/null +++ b/src/iteration/initializer/initialize_fixed_terms_reset_moments.hpp @@ -0,0 +1,28 @@ +#ifndef BART_SRC_ITERATION_INITIALIZER_INITIALIZE_FIXED_TERMS_RESET_MOMENTS_HPP_ +#define BART_SRC_ITERATION_INITIALIZER_INITIALIZE_FIXED_TERMS_RESET_MOMENTS_HPP_ + +#include "iteration/initializer/initialize_fixed_terms.h" + +namespace bart::iteration::initializer { + +class InitializeFixedTermsResetMoments : public InitializeFixedTerms { + public: + using FixedUpdater = InitializeFixedTerms::FixedUpdaterType; + InitializeFixedTermsResetMoments(std::shared_ptr fixed_updater_ptr, const int total_groups, + const int total_angles) + : InitializeFixedTerms(fixed_updater_ptr, total_groups, total_angles) {} + + void Initialize(system::System &system) override { + for (auto& [index, moment] : *system.current_moments) + moment = 1.0; + for (auto& [index, moment] : *system.previous_moments) + moment = 1.0; + system.k_effective = std::nullopt; + InitializeFixedTerms::Initialize(system); + } + +}; + +} // namespace bart::iteration::initializer + +#endif //BART_SRC_ITERATION_INITIALIZER_INITIALIZE_FIXED_TERMS_RESET_MOMENTS_HPP_ diff --git a/src/iteration/initializer/tests/initialize_fixed_terms_reset_moments.cpp b/src/iteration/initializer/tests/initialize_fixed_terms_reset_moments.cpp new file mode 100644 index 000000000..267b79bbe --- /dev/null +++ b/src/iteration/initializer/tests/initialize_fixed_terms_reset_moments.cpp @@ -0,0 +1,96 @@ +#include "iteration/initializer/initialize_fixed_terms_reset_moments.hpp" + +#include "formulation/updater/tests/fixed_updater_mock.h" +#include "system/moments/spherical_harmonic_types.h" +#include "system/moments/tests/spherical_harmonic_mock.h" +#include "test_helpers/gmock_wrapper.h" +#include "test_helpers/test_helper_functions.h" + +namespace { + +using namespace bart; + +using ::testing::ContainerEq, ::testing::DoDefault, ::testing::NiceMock, ::testing::Ref, ::testing::Return; + +class InitializeFixedTermsResetMomentsTest : public ::testing::Test { + public: + using FixedUpdater = formulation::updater::FixedUpdaterMock; + using TestInitializer = iteration::initializer::InitializeFixedTermsResetMoments; + using SphericalHarmonics = NiceMock; + + // Test object + std::unique_ptr test_initializer_ptr_{ nullptr }; + + // Supporting objects + system::System test_system_; + + // Supporting mocks + std::shared_ptr fixed_updater_ptr_{ nullptr }; + SphericalHarmonics* previous_moments_obs_ptr_, *current_moments_obs_ptr_; + system::moments::MomentsMap previous_moments_map_, current_moments_map_; + system::moments::MomentsMap reset_moments_map_; + + // Test parameters + const int n_groups{ test_helpers::RandomInt(1, 5) }; + const int n_angles{ test_helpers::RandomInt(2, 3) }; + const int max_harmonic_l{ test_helpers::RandomInt(2, 3) }; + const int moment_vector_size{ test_helpers::RandomInt(10, 20) }; + + // Test functions + auto SetUp() -> void override; +}; + +auto InitializeFixedTermsResetMomentsTest::SetUp() -> void { + for (int group = 0; group < n_groups; ++group) { + for (int harmonic_l = 0; harmonic_l < max_harmonic_l; ++harmonic_l) { + for (int harmonic_m = -harmonic_l; harmonic_m <= harmonic_l; ++harmonic_m) { + dealii::Vector previous_moment(moment_vector_size), current_moment(moment_vector_size); + dealii::Vector reset_moment(moment_vector_size); + previous_moment = 2.0; + current_moment = 2.0; + reset_moment = 1.0; + previous_moments_map_[{group, harmonic_l, harmonic_m}] = previous_moment; + current_moments_map_[{group, harmonic_l, harmonic_m}] = current_moment; + reset_moments_map_[{group, harmonic_l, harmonic_m}] = reset_moment; + } + } + } + test_system_.current_moments = std::make_unique(); + test_system_.previous_moments = std::make_unique(); + current_moments_obs_ptr_ = dynamic_cast(test_system_.current_moments.get()); + previous_moments_obs_ptr_ = dynamic_cast(test_system_.previous_moments.get()); + + ON_CALL(*current_moments_obs_ptr_, begin()).WillByDefault(Return(current_moments_map_.begin())); + ON_CALL(*current_moments_obs_ptr_, end()).WillByDefault(Return(current_moments_map_.end())); + ON_CALL(*previous_moments_obs_ptr_, begin()).WillByDefault(Return(previous_moments_map_.begin())); + ON_CALL(*previous_moments_obs_ptr_, end()).WillByDefault(Return(previous_moments_map_.end())); + + test_system_.k_effective = test_helpers::RandomDouble(0, 100); + + fixed_updater_ptr_ = std::make_shared(); + test_initializer_ptr_ = std::make_unique(fixed_updater_ptr_, n_groups, n_angles); +} + + + +TEST_F(InitializeFixedTermsResetMomentsTest, InitializeAndReset) { + for (int group = 0; group < n_groups; ++group) { + for (int angle = 0; angle < n_angles; ++angle) { + system::EnergyGroup energy_group(group); + quadrature::QuadraturePointIndex angle_index(angle); + EXPECT_CALL(*fixed_updater_ptr_, UpdateFixedTerms(Ref(test_system_), energy_group, angle_index)); + } + } + EXPECT_CALL(*current_moments_obs_ptr_, begin()).WillOnce(DoDefault()); + EXPECT_CALL(*current_moments_obs_ptr_, end()).WillOnce(DoDefault()); + EXPECT_CALL(*previous_moments_obs_ptr_, begin()).WillOnce(DoDefault()); + EXPECT_CALL(*previous_moments_obs_ptr_, end()).WillOnce(DoDefault()); + + test_initializer_ptr_->Initialize(test_system_); + + EXPECT_THAT(current_moments_map_, ContainerEq(reset_moments_map_)); + EXPECT_THAT(previous_moments_map_, ContainerEq(reset_moments_map_)); + EXPECT_EQ(test_system_.k_effective, std::nullopt); +} + +} // namespace \ No newline at end of file diff --git a/src/iteration/outer/outer_iteration.cpp b/src/iteration/outer/outer_iteration.cpp index c6285a2aa..7e484a885 100644 --- a/src/iteration/outer/outer_iteration.cpp +++ b/src/iteration/outer/outer_iteration.cpp @@ -25,8 +25,11 @@ void OuterIteration::IterateToConvergence( bool is_complete{ false }; do { is_complete = Iterate(system); - if (post_iteration_subroutine_ptr_ != nullptr) + if (post_iteration_subroutine_ptr_ != nullptr) { + data_names::StatusPort::Expose("===================== COMMENCING SUBROUTINE =====================\n"); post_iteration_subroutine_ptr_->Execute(system); + data_names::StatusPort::Expose("===================== COMPLETED SUBROUTINE =====================\n"); + } } while (!is_complete); } diff --git a/src/problem/parameter_types.h b/src/problem/parameter_types.hpp similarity index 86% rename from src/problem/parameter_types.h rename to src/problem/parameter_types.hpp index 0d37e18bd..fc47a6928 100644 --- a/src/problem/parameter_types.h +++ b/src/problem/parameter_types.hpp @@ -1,5 +1,5 @@ -#ifndef BART_SRC_PROBLEM_PARAMETER_TYPES_H_ -#define BART_SRC_PROBLEM_PARAMETER_TYPES_H_ +#ifndef BART_SRC_PROBLEM_PARAMETER_TYPES_HPP_ +#define BART_SRC_PROBLEM_PARAMETER_TYPES_HPP_ namespace bart { @@ -34,6 +34,7 @@ enum class EigenSolverType { enum class EquationType { kNone, kDiffusion, + kDriftDiffusion, kEvenParity, kSelfAdjointAngularFlux, }; @@ -79,4 +80,4 @@ enum class PreconditionerType { } // namespace bart -#endif // BART_SRC_PROBLEM_PARAMETER_TYPES_H_ +#endif // BART_SRC_PROBLEM_PARAMETER_TYPES_HPP_ diff --git a/src/problem/parameters_dealii_handler.h b/src/problem/parameters_dealii_handler.h index 833007e71..fa7223a95 100644 --- a/src/problem/parameters_dealii_handler.h +++ b/src/problem/parameters_dealii_handler.h @@ -8,7 +8,7 @@ #include #include "parameters_i.h" -#include "parameter_types.h" +#include "parameter_types.hpp" namespace bart { diff --git a/src/problem/parameters_i.h b/src/problem/parameters_i.h index 8ffd998da..f37f0007b 100644 --- a/src/problem/parameters_i.h +++ b/src/problem/parameters_i.h @@ -7,7 +7,8 @@ #include #include "eigenvalue/k_effective/factory.hpp" -#include "parameter_types.h" +#include "parameter_types.hpp" + namespace bart { diff --git a/src/problem/tests/parameters_dealii_handler_test.cc b/src/problem/tests/parameters_dealii_handler_test.cc index 8a295e330..341b33526 100644 --- a/src/problem/tests/parameters_dealii_handler_test.cc +++ b/src/problem/tests/parameters_dealii_handler_test.cc @@ -7,7 +7,7 @@ #include "gtest/gtest.h" -#include "../parameter_types.h" +#include "../parameter_types.hpp" class ParametersDealiiHandlerTest : public ::testing::Test { protected: diff --git a/src/quadrature/quadrature_set_i.h b/src/quadrature/quadrature_set_i.h index 951cfe6c3..6ab091b3c 100644 --- a/src/quadrature/quadrature_set_i.h +++ b/src/quadrature/quadrature_set_i.h @@ -3,7 +3,7 @@ #include "quadrature/quadrature_point_i.h" #include "quadrature/quadrature_types.h" -#include "problem/parameter_types.h" +#include "problem/parameter_types.hpp" #include #include