From a800f2976b2b98c9a04d8a5bf2ecc403fa0b90a9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 6 Nov 2018 06:28:36 -0600 Subject: [PATCH] Move res_scat_nuclides to C++ --- include/openmc/cross_sections.h | 13 ++++++++++++- include/openmc/settings.h | 1 + src/api.F90 | 3 +++ src/cross_sections.cpp | 32 ++++++++++++++++++++++++-------- src/input_xml.F90 | 14 -------------- src/nuclide_header.F90 | 25 ++++++++++++++++++++++--- src/settings.F90 | 18 ------------------ src/settings.cpp | 21 +++++++++++++++++++-- 8 files changed, 81 insertions(+), 46 deletions(-) diff --git a/include/openmc/cross_sections.h b/include/openmc/cross_sections.h index eaa4f5632..2b7a94f80 100644 --- a/include/openmc/cross_sections.h +++ b/include/openmc/cross_sections.h @@ -9,6 +9,10 @@ namespace openmc { +//============================================================================== +// Library class +//============================================================================== + class Library { public: // Types, enums @@ -30,14 +34,21 @@ public: std::string path_; }; +//============================================================================== +// Global variable declarations +//============================================================================== + extern std::vector libraries; using LibraryKey = std::pair; extern std::map library_dict; +//============================================================================== +// Non-member functions +//============================================================================== extern "C" void read_cross_sections_xml(); void read_ce_cross_sections_xml(); -} +} // namespace openmc #endif // OPENMC_CROSS_SECTIONS_H diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 47ca0f078..3296c5b20 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -77,6 +77,7 @@ extern "C" int n_max_batches; //!< Maximum number of batches extern "C" int res_scat_method; //!< resonance upscattering method extern "C" double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering extern "C" double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering +extern std::vector res_scat_nuclides; //!< Nuclides using res. upscattering treatment extern "C" int run_mode; //!< Run mode (eigenvalue, fixed src, etc.) extern std::unordered_set sourcepoint_batch; //!< Batches when source should be written extern std::unordered_set statepoint_batch; //!< Batches when state should be written diff --git a/src/api.F90 b/src/api.F90 index bb99180cc..efcfa16a6 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -79,6 +79,9 @@ contains subroutine free_memory_mesh() bind(C) end subroutine free_memory_mesh + + subroutine free_memory_settings() bind(C) + end subroutine free_memory_settings end interface call free_memory_geometry() diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp index 94172f162..3cc4320fe 100644 --- a/src/cross_sections.cpp +++ b/src/cross_sections.cpp @@ -15,11 +15,19 @@ namespace openmc { +//============================================================================== +// Global variable declarations +//============================================================================== + std::vector libraries; std::map library_dict; extern "C" void read_mg_cross_sections_header(); +//============================================================================== +// Library methods +//============================================================================== + Library::Library(pugi::xml_node node, const std::string& directory) { // Get type of library @@ -64,6 +72,9 @@ Library::Library(pugi::xml_node node, const std::string& directory) } } +//============================================================================== +// Non-member functions +//============================================================================== void read_cross_sections_xml() { @@ -145,14 +156,15 @@ void read_cross_sections_xml() } // Check that 0K nuclides are listed in the cross_sections.xml file - // if (allocated(res_scat_nuclides)) { - // do i = 1, size(res_scat_nuclides) - // if (!library_dict % has(to_lower(res_scat_nuclides(i)))) { - // fatal_error("Could not find resonant scatterer " & - // // trim(res_scat_nuclides(i)) // " in cross_sections.xml file!") - // } - // end do - // } + for (const auto& name : settings::res_scat_nuclides) { + std::string lower_name = name; + to_lower(lower_name); + LibraryKey key {Library::Type::neutron, lower_name}; + if (library_dict.find(key) == library_dict.end()) { + fatal_error("Could not find resonant scatterer " + + name + " in cross_sections.xml file!"); + } + } } void read_ce_cross_sections_xml() @@ -196,6 +208,10 @@ void read_ce_cross_sections_xml() } } +//============================================================================== +// Fortran compatibility functions +//============================================================================== + extern "C" void library_clear() { libraries.clear(); library_dict.clear(); diff --git a/src/input_xml.F90 b/src/input_xml.F90 index fb8a8d772..fbd632906 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -223,20 +223,6 @@ contains ! Get proper XMLNode type given pointer root % ptr = root_ptr - ! Resonance scattering parameters - if (check_for_node(root, "resonance_scattering")) then - node_res_scat = root % child("resonance_scattering") - - ! Get nuclides that resonance scattering should be applied to - if (check_for_node(node_res_scat, "nuclides")) then - n = node_word_count(node_res_scat, "nuclides") - allocate(res_scat_nuclides(n)) - if (n > 0) then - call get_node_array(node_res_scat, "nuclides", res_scat_nuclides) - end if - end if - end if - call get_node_list(root, "volume_calc", node_vol_list) n = size(node_vol_list) allocate(volume_calcs(n)) diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index a506b623c..db4b13be6 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -240,11 +240,30 @@ contains integer :: i real(8) :: xs_cdf_sum + interface + function res_scat_nuclides_empty() result(empty) bind(C) + import C_BOOL + logical(C_BOOL) :: empty + end function + + function res_scat_nuclides_size() result(n) bind(C) + import C_INT + integer(C_INT) :: n + end function + + function res_scat_nuclides_cmp(i, name) result(b) bind(C) + import C_INT, C_CHAR, C_BOOL + integer(C_INT), value :: i + character(kind=C_CHAR), intent(in) :: name(*) + logical(C_BOOL) :: b + end function + end interface + this % resonant = .false. - if (allocated(res_scat_nuclides)) then + if (.not. res_scat_nuclides_empty()) then ! If resonant nuclides were specified, check the list explicitly - do i = 1, size(res_scat_nuclides) - if (this % name == res_scat_nuclides(i)) then + do i = 1, res_scat_nuclides_size() + if (res_scat_nuclides_cmp(i, to_c_string(this % name))) then this % resonant = .true. ! Make sure nuclide has 0K data diff --git a/src/settings.F90 b/src/settings.F90 index 19ec3f771..665c0e481 100644 --- a/src/settings.F90 +++ b/src/settings.F90 @@ -115,7 +115,6 @@ module settings integer(C_INT), bind(C) :: res_scat_method ! resonance scattering method real(C_DOUBLE), bind(C) :: res_scat_energy_min real(C_DOUBLE), bind(C) :: res_scat_energy_max - character(10), allocatable :: res_scat_nuclides(:) ! Is CMFD active logical(C_BOOL), bind(C) :: cmfd_run @@ -123,21 +122,4 @@ module settings ! No reduction at end of batch logical(C_BOOL), bind(C) :: reduce_tallies -contains - -!=============================================================================== -! FREE_MEMORY_SETTINGS deallocates global arrays defined in this module -!=============================================================================== - - subroutine free_memory_settings() - interface - subroutine free_memory_settings_c() bind(C) - end subroutine - end interface - - if (allocated(res_scat_nuclides)) deallocate(res_scat_nuclides) - - call free_memory_settings_c() - end subroutine free_memory_settings - end module settings diff --git a/src/settings.cpp b/src/settings.cpp index ce81c6b63..c1cd54c88 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -88,6 +88,7 @@ int n_max_batches; int res_scat_method {RES_SCAT_ARES}; double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; +std::vector res_scat_nuclides; int run_mode {-1}; std::unordered_set sourcepoint_batch; std::unordered_set statepoint_batch; @@ -749,7 +750,10 @@ void read_settings_xml() "lower resonance scattering energy bound."); } - // TODO: Get resonance scattering nuclides + // Get resonance scattering nuclides + if (check_for_node(node_res_scat, "nuclides")) { + res_scat_nuclides = get_node_array(node_res_scat, "nuclides"); + } } // TODO: Get volume calculations @@ -817,6 +821,18 @@ void read_settings_xml() //============================================================================== extern "C" { + bool res_scat_nuclides_empty() { + return settings::res_scat_nuclides.empty(); + } + + int res_scat_nuclides_size() { + return settings::res_scat_nuclides.size(); + } + + bool res_scat_nuclides_cmp(int i, const char* name) { + return settings::res_scat_nuclides[i - 1] == name; + } + const char* openmc_path_input() { return settings::path_input.c_str(); } @@ -830,9 +846,10 @@ extern "C" { return settings::path_particle_restart.c_str(); } - void free_memory_settings_c() { + void free_memory_settings() { settings::statepoint_batch.clear(); settings::sourcepoint_batch.clear(); + settings::res_scat_nuclides.clear(); } }