diff --git a/CMakeLists.txt b/CMakeLists.txt index fded5876c3..e76ed9a9e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,7 @@ add_library(libopenmc SHARED src/dagmc.cpp src/cell.cpp src/cmfd_execute.cpp + src/cross_sections.cpp src/distribution.cpp src/distribution_angle.cpp src/distribution_energy.cpp diff --git a/include/openmc/cross_sections.h b/include/openmc/cross_sections.h new file mode 100644 index 0000000000..eaa4f56324 --- /dev/null +++ b/include/openmc/cross_sections.h @@ -0,0 +1,43 @@ +#ifndef OPENMC_CROSS_SECTIONS_H +#define OPENMC_CROSS_SECTIONS_H + +#include "pugixml.hpp" + +#include +#include +#include + +namespace openmc { + +class Library { +public: + // Types, enums + enum class Type { + neutron = 1, photon = 3, thermal = 2, multigroup = 4, wmp = 5 + }; + + // Constructors + Library(pugi::xml_node node, const std::string& directory); + + // Comparison operator (for using in map) + bool operator<(const Library& other) { + return path_ < other.path_; + } + + // Data members + Type type_; + std::vector materials_; + std::string path_; +}; + +extern std::vector libraries; +using LibraryKey = std::pair; +extern std::map library_dict; + + +extern "C" void read_cross_sections_xml(); +void read_ce_cross_sections_xml(); + +} + +#endif // OPENMC_CROSS_SECTIONS_H diff --git a/include/openmc/string_utils.h b/include/openmc/string_utils.h index 9af50870db..73b1a28ecf 100644 --- a/include/openmc/string_utils.h +++ b/include/openmc/string_utils.h @@ -38,5 +38,12 @@ ends_with(const std::string& value, const std::string& ending) return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } +inline bool +starts_with(const std::string& value, const std::string& beginning) +{ + if (beginning.size() > value.size()) return false; + return std::equal(beginning.begin(), beginning.end(), value.begin()); +} + } // namespace openmc #endif // OPENMC_STRING_UTILS_H diff --git a/src/constants.F90 b/src/constants.F90 index 250b1ef376..857d6ae4a3 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -238,7 +238,8 @@ module constants LIBRARY_NEUTRON = 1, & LIBRARY_THERMAL = 2, & LIBRARY_PHOTON = 3, & - LIBRARY_MULTIGROUP = 4 + LIBRARY_MULTIGROUP = 4, & + LIBRARY_WMP = 5 ! Probability table parameters integer, parameter :: & diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp new file mode 100644 index 0000000000..94172f162c --- /dev/null +++ b/src/cross_sections.cpp @@ -0,0 +1,221 @@ +#include "openmc/cross_sections.h" + +#include "openmc/constants.h" +#include "openmc/container_util.h" +#include "openmc/error.h" +#include "openmc/file_utils.h" +#include "openmc/settings.h" +#include "openmc/string_functions.h" +#include "openmc/string_utils.h" +#include "openmc/xml_interface.h" + +#include "pugixml.hpp" + +#include // for getenv + +namespace openmc { + +std::vector libraries; +std::map library_dict; + +extern "C" void read_mg_cross_sections_header(); + +Library::Library(pugi::xml_node node, const std::string& directory) +{ + // Get type of library + if (check_for_node(node, "type")) { + auto type = get_node_value(node, "type"); + if (type == "neutron") { + type_ = Type::neutron; + } else if (type == "thermal") { + type_ = Type::thermal; + } else if (type == "photon") { + type_ = Type::photon; + } else if (type == "wmp") { + type_ = Type::wmp; + } else { + fatal_error("Unrecognized library type: " + type); + } + } else { + fatal_error("Missing library type"); + } + + // Get list of materials + if (check_for_node(node, "materials")) { + materials_ = get_node_array(node, "materials"); + } + + // determine path of cross section table + if (!check_for_node(node, "path")) { + fatal_error("Missing library path"); + } + std::string path = get_node_value(node, "path"); + + if (starts_with(path, "/")) { + path_ = path; + } else if (ends_with(directory, "/")) { + path_ = directory + path; + } else { + path_ = directory + "/" + path; + } + + if (!file_exists(path_)) { + warning("Cross section library " + path_ + " does not exist."); + } +} + + +void read_cross_sections_xml() +{ + // Check if materials.xml exists + std::string filename = settings::path_input + "materials.xml"; + if (!file_exists(filename)) { + fatal_error("Material XML file '" + filename + "' does not exist."); + } + + // Parse materials.xml file + pugi::xml_document doc; + doc.load_file(filename.c_str()); + auto root = doc.document_element(); + + // Find cross_sections.xml file -- the first place to look is the + // materials.xml file. If no file is found there, then we check the + // OPENMC_CROSS_SECTIONS environment variable + if (!check_for_node(root, "cross_sections")) { + // No cross_sections.xml file specified in settings.xml, check + // environment variable + if (settings::run_CE) { + char* envvar = std::getenv("OPENMC_CROSS_SECTIONS"); + if (!envvar) { + fatal_error("No cross_sections.xml file was specified in " + "materials.xml or in the OPENMC_CROSS_SECTIONS" + " environment variable. OpenMC needs such a file to identify " + "where to find data libraries. Please consult the" + " user's guide at https://openmc.readthedocs.io for " + "information on how to set up data libraries."); + } + settings::path_cross_sections = envvar; + } else { + char* envvar = std::getenv("OPENMC_MG_CROSS_SECTIONS"); + if (!envvar) { + fatal_error("No mgxs.h5 file was specified in " + "materials.xml or in the OPENMC_MG_CROSS_SECTIONS environment " + "variable. OpenMC needs such a file to identify where to " + "find MG cross section libraries. Please consult the user's " + "guide at http://openmc.readthedocs.io for information on " + "how to set up MG cross section libraries."); + } + settings::path_cross_sections = envvar; + } + } else { + settings::path_cross_sections = get_node_value(root, "cross_sections"); + } + + // Find the windowed multipole library + if (settings::run_mode != RUN_MODE_PLOTTING) { + if (!check_for_node(root, "multipole_library")) { + // No library location specified in materials.xml, check + // environment variable + settings::path_multipole = std::getenv("OPENMC_MULTIPOLE_LIBRARY"); + } else { + settings::path_multipole = get_node_value(root, "multipole_library"); + } + if (!ends_with(settings::path_multipole, "/")) { + settings::path_multipole += "/"; + } + } + + // Now that the cross_sections.xml or mgxs.h5 has been located, read it in + if (settings::run_CE) { + read_ce_cross_sections_xml(); + } else { + read_mg_cross_sections_header(); + } + + // Establish mapping between (type, material) and index in libraries + int i = 0; + for (const auto& lib : libraries) { + for (const auto& name : lib.materials_) { + std::string lower_name = name; + to_lower(lower_name); + LibraryKey key {lib.type_, lower_name}; + library_dict.insert({key, i}); + } + ++i; + } + + // 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 + // } +} + +void read_ce_cross_sections_xml() +{ + // Check if cross_sections.xml exists + const auto& filename = settings::path_cross_sections; + if (!file_exists(filename)) { + // Could not find cross_sections.xml file + fatal_error("Cross sections XML file '" + filename + + "' does not exist."); + } + + write_message("Reading cross sections XML file...", 5); + + // Parse cross_sections.xml file + pugi::xml_document doc; + auto result = doc.load_file(filename.c_str()); + if (!result) { + fatal_error("Error processing cross_sections.xml file."); + } + auto root = doc.document_element(); + + std::string directory; + if (check_for_node(root, "directory")) { + // Copy directory information if present + directory = get_node_value(root, "directory"); + } else { + // If no directory is listed in cross_sections.xml, by default select the + // directory in which the cross_sections.xml file resides + auto pos = filename.rfind("/"); + directory = filename.substr(0, pos); + } + + for (const auto& node_library : root.children("library")) { + libraries.emplace_back(node_library, directory); + } + + // Make sure file was not empty + if (libraries.empty()) { + fatal_error("No cross section libraries present in cross_sections.xml file."); + } +} + +extern "C" void library_clear() { + libraries.clear(); + library_dict.clear(); +} + +extern "C" const char* library_path(int type, const char* name) { + auto lib_type = static_cast(type); + LibraryKey key {lib_type, name}; + if (library_dict.find(key) == library_dict.end()) { + return nullptr; + } else { + auto idx = library_dict[key]; + return libraries[idx].path_.c_str(); + } +} + +extern "C" bool library_present(int type, const char* name) { + auto lib_type = static_cast(type); + LibraryKey key {lib_type, name}; + return library_dict.find(key) != library_dict.end(); +} + +} // namespace openmc diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 04f53d1688..fb8a8d772b 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -72,6 +72,9 @@ module input_xml type(C_PTR) :: node_ptr end subroutine read_cells + subroutine read_cross_sections_xml() bind(C) + end subroutine + subroutine read_lattices(node_ptr) bind(C) import C_PTR type(C_PTR) :: node_ptr @@ -545,119 +548,6 @@ contains end do end subroutine allocate_cells -!=============================================================================== -! READ_MATERIAL_XML reads data from a materials.xml file and parses it, checking -! for errors and placing properly-formatted data in the right data structures -!=============================================================================== - - subroutine read_cross_sections_xml() - integer :: i, j - logical :: file_exists - character(MAX_FILE_LEN) :: env_variable - character(MAX_LINE_LEN) :: filename - type(XMLDocument) :: doc - type(XMLNode) :: root - - ! Check if materials.xml exists - filename = trim(path_input) // "materials.xml" - inquire(FILE=filename, EXIST=file_exists) - if (.not. file_exists) then - call fatal_error("Material XML file '" // trim(filename) // "' does not & - &exist!") - end if - - ! Parse materials.xml file - call doc % load_file(filename) - root = doc % document_element() - - ! Find cross_sections.xml file -- the first place to look is the - ! materials.xml file. If no file is found there, then we check the - ! OPENMC_CROSS_SECTIONS environment variable - if (.not. check_for_node(root, "cross_sections")) then - ! No cross_sections.xml file specified in settings.xml, check - ! environment variable - if (run_CE) then - call get_environment_variable("OPENMC_CROSS_SECTIONS", env_variable) - if (len_trim(env_variable) == 0) then - call get_environment_variable("CROSS_SECTIONS", env_variable) - ! FIXME: When deprecated option of setting the cross sections in - ! settings.xml is removed, remove ".and. path_cross_sections == ''" - if (len_trim(env_variable) == 0 .and. path_cross_sections == '') then - call fatal_error("No cross_sections.xml file was specified in & - &materials.xml, settings.xml, or in the OPENMC_CROSS_SECTIONS& - & environment variable. OpenMC needs such a file to identify & - &where to find ACE cross section libraries. Please consult the& - & user's guide at http://openmc.readthedocs.io for & - &information on how to set up ACE cross section libraries.") - else - call warning("The CROSS_SECTIONS environment variable is & - &deprecated. Please update your environment to use & - &OPENMC_CROSS_SECTIONS instead.") - end if - end if - path_cross_sections = trim(env_variable) - else - call get_environment_variable("OPENMC_MG_CROSS_SECTIONS", env_variable) - ! FIXME: When deprecated option of setting the mg cross sections in - ! settings.xml is removed, remove ".and. path_cross_sections == ''" - if (len_trim(env_variable) == 0 .and. path_cross_sections == '') then - call fatal_error("No mgxs.h5 file was specified in & - &materials.xml or in the OPENMC_MG_CROSS_SECTIONS environment & - &variable. OpenMC needs such a file to identify where to & - &find MG cross section libraries. Please consult the user's & - &guide at http://openmc.readthedocs.io for information on & - &how to set up MG cross section libraries.") - else if (len_trim(env_variable) /= 0) then - path_cross_sections = trim(env_variable) - end if - end if - else - call get_node_value(root, "cross_sections", path_cross_sections) - end if - - ! Find the windowed multipole library - if (run_mode /= MODE_PLOTTING) then - if (.not. check_for_node(root, "multipole_library")) then - ! No library location specified in materials.xml, check - ! environment variable - call get_environment_variable("OPENMC_MULTIPOLE_LIBRARY", env_variable) - path_multipole = trim(env_variable) - else - call get_node_value(root, "multipole_library", path_multipole) - end if - if (.not. ends_with(path_multipole, "/")) & - path_multipole = trim(path_multipole) // "/" - end if - - ! Close materials XML file - call doc % clear() - - ! Now that the cross_sections.xml or mgxs.h5 has been located, read it in - if (run_CE) then - call read_ce_cross_sections_xml() - else - call read_mg_cross_sections_header() - end if - - ! Creating dictionary that maps the name of the material to the entry - do i = 1, size(libraries) - do j = 1, size(libraries(i) % materials) - call library_dict % set(to_lower(libraries(i) % materials(j)), i) - end do - end do - - ! Check that 0K nuclides are listed in the cross_sections.xml file - if (allocated(res_scat_nuclides)) then - do i = 1, size(res_scat_nuclides) - if (.not. library_dict % has(to_lower(res_scat_nuclides(i)))) then - call fatal_error("Could not find resonant scatterer " & - // trim(res_scat_nuclides(i)) // " in cross_sections.xml file!") - end if - end do - end if - - end subroutine read_cross_sections_xml - subroutine read_materials_xml() integer :: i ! loop index for materials integer :: j ! loop index for nuclides @@ -928,19 +818,10 @@ contains ALL_NUCLIDES: do j = 1, mat % n_nuclides ! Check that this nuclide is listed in the cross_sections.xml file name = trim(names % data(j)) - if (.not. library_dict % has(to_lower(name))) then + if (.not. library_present(LIBRARY_NEUTRON, (to_lower(name)))) then call fatal_error("Could not find nuclide " // trim(name) & // " in cross_sections data file!") end if - i_library = library_dict % get(to_lower(name)) - - if (run_CE) then - ! Check to make sure cross-section is continuous energy neutron table - if (libraries(i_library) % type /= LIBRARY_NEUTRON) then - call fatal_error("Cross-section table " // trim(name) & - // " is not a continuous-energy neutron table.") - end if - end if ! If this nuclide hasn't been encountered yet, we need to add its name ! and alias to the nuclide_dict @@ -959,7 +840,7 @@ contains element = name(1:scan(name, '0123456789') - 1) ! Make sure photon cross section data is available - if (.not. library_dict % has(to_lower(element))) then + if (.not. library_present(LIBRARY_PHOTON, to_lower(element))) then call fatal_error("Could not find element " // trim(element) & // " in cross_sections data file!") end if @@ -1053,23 +934,11 @@ contains end if ! Check that this nuclide is listed in the cross_sections.xml file - if (.not. library_dict % has(to_lower(name))) then + if (.not. library_present(LIBRARY_THERMAL, to_lower(name))) then call fatal_error("Could not find S(a,b) table " // trim(name) & // " in cross_sections.xml file!") end if - ! Find index in xs_listing and set the name and alias according to the - ! listing - i_library = library_dict % get(to_lower(name)) - - if (run_CE) then - ! Check to make sure cross-section is continuous energy neutron table - if (libraries(i_library) % type /= LIBRARY_THERMAL) then - call fatal_error("Cross-section table " // trim(name) & - // " is not a S(a,b) table.") - end if - end if - ! If this S(a,b) table hasn't been encountered yet, we need to add its ! name and alias to the sab_dict if (.not. sab_dict % has(to_lower(name))) then @@ -2052,117 +1921,7 @@ contains end subroutine read_plots_xml -!=============================================================================== -! READ_*_CROSS_SECTIONS_XML reads information from a cross_sections.xml file. This -! file contains a listing of the CE and MG cross sections that may be used. -!=============================================================================== - - subroutine read_ce_cross_sections_xml() - integer :: i ! loop index - integer :: n - integer :: n_libraries - logical :: file_exists ! does cross_sections.xml exist? - character(MAX_WORD_LEN) :: directory ! directory with cross sections - character(MAX_WORD_LEN) :: words(MAX_WORDS) - character(10000) :: temp_str - type(XMLDocument) :: doc - type(XMLNode) :: root - type(XMLNode) :: node_library - type(XMLNode), allocatable :: node_library_list(:) - - ! Check if cross_sections.xml exists - inquire(FILE=path_cross_sections, EXIST=file_exists) - if (.not. file_exists) then - ! Could not find cross_sections.xml file - call fatal_error("Cross sections XML file '" & - // trim(path_cross_sections) // "' does not exist!") - end if - - call write_message("Reading cross sections XML file...", 5) - - ! Parse cross_sections.xml file - call doc % load_file(path_cross_sections) - root = doc % document_element() - - if (check_for_node(root, "directory")) then - ! Copy directory information if present - call get_node_value(root, "directory", directory) - else - ! If no directory is listed in cross_sections.xml, by default select the - ! directory in which the cross_sections.xml file resides - i = index(path_cross_sections, "/", BACK=.true.) - directory = path_cross_sections(1:i) - end if - - ! Get node list of all - call get_node_list(root, "library", node_library_list) - n_libraries = size(node_library_list) - - ! Allocate xs_listings array - if (n_libraries == 0) then - call fatal_error("No cross section libraries present in cross_sections.xml & - &file!") - else - allocate(libraries(n_libraries)) - end if - - do i = 1, n_libraries - ! Get pointer to ace table XML node - node_library = node_library_list(i) - - ! Get list of materials - if (check_for_node(node_library, "materials")) then - call get_node_value(node_library, "materials", temp_str) - call split_string(temp_str, words, n) - allocate(libraries(i) % materials(n)) - libraries(i) % materials(:) = words(1:n) - end if - - ! Get type of library - if (check_for_node(node_library, "type")) then - call get_node_value(node_library, "type", temp_str) - select case(to_lower(temp_str)) - case ('neutron') - libraries(i) % type = LIBRARY_NEUTRON - case ('thermal') - libraries(i) % type = LIBRARY_THERMAL - case ('photon') - libraries(i) % type = LIBRARY_PHOTON - end select - else - call fatal_error("Missing library type") - end if - - ! determine path of cross section table - if (check_for_node(node_library, "path")) then - call get_node_value(node_library, "path", temp_str) - else - call fatal_error("Missing library path") - end if - - if (starts_with(temp_str, '/')) then - libraries(i) % path = trim(temp_str) - else - if (ends_with(directory,'/')) then - libraries(i) % path = trim(directory) // trim(temp_str) - else - libraries(i) % path = trim(directory) // '/' // trim(temp_str) - end if - end if - - inquire(FILE=libraries(i) % path, EXIST=file_exists) - if (.not. file_exists) then - call warning("Cross section library " // trim(libraries(i) % path) // & - " does not exist.") - end if - end do - - ! Close cross sections XML file - call doc % clear() - - end subroutine read_ce_cross_sections_xml - - subroutine read_mg_cross_sections_header() + subroutine read_mg_cross_sections_header() bind(C) integer :: i ! loop index integer :: n_libraries logical :: file_exists ! does mgxs.h5 exist? @@ -2240,16 +1999,8 @@ contains if (n_libraries == 0) then call fatal_error("At least one MGXS data set must be present in & &mgxs library file!") - else - allocate(libraries(n_libraries)) end if - do i = 1, n_libraries - ! Get name of material - allocate(libraries(i) % materials(1)) - libraries(i) % materials(1) = names(i) - end do - ! Close MGXS HDF5 file call file_close(file_id) @@ -2346,6 +2097,7 @@ contains integer(HID_T) :: group_id logical :: mp_found ! if windowed multipole libraries were found character(MAX_WORD_LEN) :: name + character(MAX_FILE_LEN) :: filename character(3) :: element type(SetChar) :: already_read type(SetChar) :: element_already_read @@ -2363,14 +2115,14 @@ contains name = materials(i) % names(j) if (.not. already_read % contains(name)) then - i_library = library_dict % get(to_lower(name)) + filename = library_path(LIBRARY_NEUTRON, to_lower(name)) i_nuclide = nuclide_dict % get(to_lower(name)) call write_message('Reading ' // trim(name) // ' from ' // & - trim(libraries(i_library) % path), 6) + trim(filename), 6) ! Open file and make sure version is sufficient - file_id = file_open(libraries(i_library) % path, 'r') + file_id = file_open(filename, 'r') call check_data_version(file_id) ! Read nuclide data from HDF5 @@ -2403,13 +2155,13 @@ contains if (photon_transport) then if (.not. element_already_read % contains(element)) then ! Read photon interaction data from HDF5 photon library - i_library = library_dict % get(to_lower(element)) + filename = library_path(LIBRARY_PHOTON, to_lower(element)) i_element = element_dict % get(element) call write_message('Reading ' // trim(element) // ' from ' // & - trim(libraries(i_library) % path), 6) + trim(filename), 6) ! Open file and make sure version is sufficient - file_id = file_open(libraries(i_library) % path, 'r') + file_id = file_open(filename, 'r') call check_data_version(file_id) ! Read element data from HDF5 @@ -2493,14 +2245,14 @@ contains name = materials(i) % sab_names(j) if (.not. already_read % contains(name)) then - i_library = library_dict % get(to_lower(name)) + filename = library_path(LIBRARY_THERMAL, to_lower(name)) i_sab = sab_dict % get(to_lower(name)) call write_message('Reading ' // trim(name) // ' from ' // & - trim(libraries(i_library) % path), 6) + trim(filename), 6) ! Open file and make sure version matches - file_id = file_open(libraries(i_library) % path, 'r') + file_id = file_open(filename, 'r') call check_data_version(file_id) ! Read S(a,b) data from HDF5 diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index da66aea4a1..a506b623c1 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -176,20 +176,6 @@ module nuclide_header real(C_DOUBLE) :: pair_production ! macroscopic pair production xs end type MaterialMacroXS -!=============================================================================== -! LIBRARY contains data read from a cross_sections.xml file -!=============================================================================== - - type Library - integer :: type - character(MAX_WORD_LEN), allocatable :: materials(:) - character(MAX_FILE_LEN) :: path - end type Library - - ! Cross section libraries - type(Library), allocatable :: libraries(:) - type(DictCharInt) :: library_dict - ! Nuclear data for each nuclide type(Nuclide), allocatable, target :: nuclides(:) integer(C_INT), bind(C) :: n_nuclides @@ -204,8 +190,46 @@ module nuclide_header real(8) :: energy_min(2) = [ZERO, ZERO] real(8) :: energy_max(2) = [INFINITY, INFINITY] + + interface + function library_present_c(type, name) result(b) bind(C, name='library_present') + import C_INT, C_CHAR, C_BOOL + integer(C_INT), value :: type + character(kind=C_CHAR), intent(in) :: name(*) + logical(C_BOOL) :: b + end function + + function library_path_c(type, name) result(path) bind(C, name='library_path') + import C_INT, C_CHAR, C_PTR + integer(C_INT), value :: type + character(kind=C_CHAR), intent(in) :: name(*) + type(C_PTR) :: path + end function + end interface + contains + function library_path(type, name) result(path) + integer, intent(in) :: type + character(len=*), intent(in) :: name + character(MAX_FILE_LEN) :: path + + type(C_PTR) :: ptr + character(kind=C_CHAR), pointer :: string(:) + + ptr = library_path_c(type, to_c_string(name)) + call c_f_pointer(ptr, string, [255]) + path = to_f_string(string) + end function + + function library_present(type, name) result(b) + integer, intent(in) :: type + character(len=*), intent(in) :: name + logical :: b + + b = library_present_c(type, to_c_string(name)) + end function + !=============================================================================== ! ASSIGN_0K_ELASTIC_SCATTERING !=============================================================================== @@ -1540,6 +1564,11 @@ contains subroutine free_memory_nuclide() integer :: i + interface + subroutine library_clear() bind(C) + end subroutine + end interface + ! Deallocate cross section data, listings, and cache if (allocated(nuclides)) then ! First call the clear routines @@ -1550,10 +1579,8 @@ contains end if n_nuclides = 0 - if (allocated(libraries)) deallocate(libraries) - call nuclide_dict % clear() - call library_dict % clear() + call library_clear() end subroutine free_memory_nuclide @@ -1593,11 +1620,11 @@ contains character(kind=C_CHAR), intent(in) :: name(*) integer(C_INT) :: err - integer :: i_library integer :: n integer(HID_T) :: file_id integer(HID_T) :: group_id character(:), allocatable :: name_ + character(MAX_FILE_LEN) :: filename real(8) :: minmax(2) = [ZERO, INFINITY] type(VectorReal) :: temperature type(Nuclide), allocatable :: new_nuclides(:) @@ -1607,7 +1634,7 @@ contains err = 0 if (.not. nuclide_dict % has(to_lower(name_))) then - if (library_dict % has(to_lower(name_))) then + if (library_present(LIBRARY_NEUTRON, to_lower(name_))) then ! allocate extra space in nuclides array n = n_nuclides allocate(new_nuclides(n + 1)) @@ -1615,10 +1642,10 @@ contains call move_alloc(FROM=new_nuclides, TO=nuclides) n = n + 1 - i_library = library_dict % get(to_lower(name_)) + filename = library_path(LIBRARY_NEUTRON, to_lower(name_)) ! Open file and make sure version is sufficient - file_id = file_open(libraries(i_library) % path, 'r') + file_id = file_open(filename, 'r') call check_data_version(file_id) ! Read nuclide data from HDF5 diff --git a/src/settings.cpp b/src/settings.cpp index d4cea83bcc..ce81c6b63a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -187,7 +187,7 @@ void read_settings_xml() using namespace pugi; // Check if settings.xml exists - std::string filename = std::string(path_input) + "settings.xml"; + std::string filename = path_input + "settings.xml"; if (!file_exists(filename)) { if (run_mode != RUN_MODE_PLOTTING) { std::stringstream msg;