fix(const.dat): added back accidently deleted const.dat

This commit is contained in:
2025-03-20 15:06:24 -04:00
39 changed files with 987 additions and 94 deletions

View File

@@ -0,0 +1,4 @@
eos:
helm: "eos/helm_table.dat"
mesh:
sphere: "mesh/sphere.msh"

View File

@@ -2,11 +2,28 @@ project('4DSSE', 'cpp', version: '0.0.1a', default_options: ['cpp_std=c++23'], m
# Add default visibility for all C++ targets
add_project_arguments('-fvisibility=default', language: 'cpp')
# Determine the mode
mode = 1
if get_option('user_mode')
mode = 0
endif
# Define DATA_DIR based on mode
if mode == 1
data_dir = meson.project_source_root() + '/assets/dynamic'
else
data_dir = get_option('prefix') + '/' + get_option('datadir') + '/4DSSE'
endif
# Pass the DATA_DIR definition to the compiler
add_project_arguments('-DDATA_DIR=' + data_dir, language : 'cpp')
# Build external dependencies first so that all the embedded resources are available to the other targets
subdir('build-config')
subdir('subprojects/PicoSHA2')
subdir('assets/static')
# Build the main project
subdir('src')
if get_option('build_tests')

View File

@@ -1 +1,2 @@
option('build_tests', type: 'boolean', value: true, description: 'Build tests')
option('user_mode', type: 'boolean', value: false, description: 'Enable user mode (set mode = 0)')

View File

@@ -46,6 +46,7 @@ bool Config::loadConfig(const std::string& configFile) {
std::cerr << "Error: " << e.what() << std::endl;
return false;
}
m_loaded = true;
return true;
}
@@ -60,3 +61,45 @@ void Config::addToCache(const std::string &key, const YAML::Node &node) {
void Config::registerUnknownKey(const std::string &key) {
unknownKeys.push_back(key);
}
bool Config::has(const std::string &key) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
if (isKeyInCache(key)) { return true; }
YAML::Node node = YAML::Clone(yamlRoot);
std::istringstream keyStream(key);
std::string subKey;
while (std::getline(keyStream, subKey, ':')) {
if (!node[subKey]) {
registerUnknownKey(key);
return false;
}
node = node[subKey]; // go deeper
}
// Key exists and is of the requested type
addToCache(key, node);
return true;
}
void recurse_keys(const YAML::Node& node, std::vector<std::string>& keyList, const std::string& path = "") {
if (node.IsMap()) {
for (const auto& it : node) {
std::string key = it.first.as<std::string>();
std::string new_path = path.empty() ? key : path + ":" + key;
recurse_keys(it.second, keyList, new_path);
}
} else {
keyList.push_back(path);
}
}
std::vector<std::string> Config::keys() const {
std::vector<std::string> keyList;
YAML::Node node = YAML::Clone(yamlRoot);
recurse_keys(node, keyList);
return keyList;
}

View File

@@ -23,14 +23,18 @@
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>
#include <stdexcept>
// Required for YAML parsing
#include "yaml-cpp/yaml.h"
// -- Forward Def of Resource manager to let it act as a friend of Config --
class ResourceManager;
/**
* @class Config
* @brief Singleton class to manage configuration settings loaded from a YAML file.
@@ -94,6 +98,21 @@ private:
*/
void registerUnknownKey(const std::string &key);
bool m_loaded = false;
// Only friends can access get without a default value
template <typename T>
T get(const std::string &key) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
if (has(key)) {
return getFromCache<T>(key, T());
} else {
throw std::runtime_error("Error! Key not found in config file");
}
}
public:
/**
* @brief Get the singleton instance of the Config class.
@@ -136,6 +155,9 @@ public:
*/
template <typename T>
T get(const std::string &key, T defaultValue) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
// --- Check if the key has already been checked for existence
if (std::find(unknownKeys.begin(), unknownKeys.end(), key) != unknownKeys.end()) {
return defaultValue; // If the key has already been added to the unknown cache do not traverse the YAML tree or hit the cache
@@ -171,6 +193,19 @@ public:
}
}
/**
* @brief Check if the key exists in the given config file
* @param key Key to check;
* @return boolean true or false
*/
bool has(const std::string &key);
/**
* @brief Get all keys defined in the configuration file.
* @return Vector of all keys in the configuration file.
*/
std::vector<std::string> keys() const;
/**
* @brief Print the configuration file path and the YAML root node.
* @param os Output stream.
@@ -178,6 +213,10 @@ public:
* @return Output stream.
*/
friend std::ostream& operator<<(std::ostream& os, const Config& config) {
if (!config.m_loaded) {
os << "Config file not loaded" << std::endl;
return os;
}
if (!config.debug) {
os << "Config file: " << config.configFilePath << std::endl;
} else{
@@ -190,6 +229,8 @@ public:
// Setup gTest class as a friend
friend class configTestPrivateAccessor;
// -- Resource Manager is a friend of config so it can create a seperate instance
friend class ResourceManager;
};
#endif

View File

@@ -1,23 +1,34 @@
# Define the library
eos_sources = files(
'private/helm.cpp',
'private/eosIO.cpp'
)
eos_headers = files(
'public/helm.h'
'public/helm.h',
'public/eosIO.h'
)
dependencies = [
const_dep,
quill_dep,
probe_dep,
config_dep,
mfem_dep,
macros_dep,
]
# Define the libconst library so it can be linked against by other parts of the build system
libeos = static_library('eos',
eos_sources,
include_directories: include_directories('public'),
cpp_args: ['-fvisibility=default'],
dependencies: [const_dep, quill_dep, probe_dep, config_dep, mfem_dep],
dependencies: dependencies,
install : true)
eos_dep = declare_dependency(
include_directories: include_directories('public'),
link_with: libeos,
dependencies: dependencies
)
# Make headers accessible
install_headers(eos_headers, subdir : '4DSSE/eos')

36
src/eos/private/eosIO.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include <string>
#include "eosIO.h"
#include "helm.h"
#include "debug.h"
EosIO::EosIO(const std::string filename) : m_filename(filename) {
load();
}
std::string EosIO::getFormat() const {
return m_format;
}
EOSTable& EosIO::getTable() {
return m_table;
}
void EosIO::load() {
// Load the EOS table from the file
// For now, just set the format to HELM
m_format = "helm";
if (m_format == "helm") {
loadHelm();
}
}
void EosIO::loadHelm() {
// Load the HELM table from the file
auto helmTabptr = helmholtz::read_helm_table(m_filename);
m_table = std::move(helmTabptr);
m_loaded = true;
}

View File

@@ -24,6 +24,7 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <sstream>
#include <cmath>
#include <string>
@@ -121,21 +122,22 @@ namespace helmholtz {
}
// this function reads in the HELM table and stores in the above arrays
HELMTable read_helm_table(const std::string filename) {
std::unique_ptr<HELMTable> read_helm_table(const std::string filename) {
Config& config = Config::getInstance();
std::string logFile = config.get<std::string>("EOS:Helm:LogFile", "log");
Probe::LogManager& logManager = Probe::LogManager::getInstance();
quill::Logger* logger = logManager.getLogger(logFile);
LOG_INFO(logger, "read_helm_table : Reading HELM table from file {}", filename);
HELMTable table;
// Make a unique pointer to the HELMTable
std::unique_ptr<HELMTable> table = std::make_unique<HELMTable>();
string data;
int i, j;
//set T and Rho (d) arrays
for (j=0; j<table.jmax; j++) { table.t[j] = pow(10, tlo + tstp*j); }
for (j=0; j<table->jmax; j++) { table->t[j] = pow(10, tlo + tstp*j); }
for (i=0; i<table.imax; i++) { table.d[i] = pow(10, dlo + dstp*i); }
for (i=0; i<table->imax; i++) { table->d[i] = pow(10, dlo + dstp*i); }
ifstream helm_table(filename);
if (!helm_table) {
@@ -144,83 +146,83 @@ namespace helmholtz {
throw std::runtime_error("Error (" + std::to_string(errorCode) + ") opening file " + filename);
}
//read the Helmholtz free energy and its derivatives
for (j=0; j<table.jmax; j++) {
for (i=0; i<table.imax; i++){
for (j=0; j<table->jmax; j++) {
for (i=0; i<table->imax; i++){
getline(helm_table, data);
stringstream id(data);
id >> table.f[i][j];
id >> table.fd[i][j];
id >> table.ft[i][j];
id >> table.fdd[i][j];
id >> table.ftt[i][j];
id >> table.fdt[i][j];
id >> table.fddt[i][j];
id >> table.fdtt[i][j];
id >> table.fddtt[i][j];
id >> table->f[i][j];
id >> table->fd[i][j];
id >> table->ft[i][j];
id >> table->fdd[i][j];
id >> table->ftt[i][j];
id >> table->fdt[i][j];
id >> table->fddt[i][j];
id >> table->fdtt[i][j];
id >> table->fddtt[i][j];
}
}
//read the pressure derivative with density
for (j=0; j<table.jmax; j++) {
for (i=0; i<table.imax; i++){
for (j=0; j<table->jmax; j++) {
for (i=0; i<table->imax; i++){
getline(helm_table, data);
stringstream id(data);
id >> table.dpdf[i][j];
id >> table.dpdfd[i][j];
id >> table.dpdft[i][j];
id >> table.dpdfdt[i][j];
id >> table->dpdf[i][j];
id >> table->dpdfd[i][j];
id >> table->dpdft[i][j];
id >> table->dpdfdt[i][j];
}
}
//read the electron chemical potential
for (j=0; j<table.jmax; j++) {
for (i=0; i<table.imax; i++){
for (j=0; j<table->jmax; j++) {
for (i=0; i<table->imax; i++){
getline(helm_table, data);
stringstream id(data);
id >> table.ef[i][j];
id >> table.efd[i][j];
id >> table.eft[i][j];
id >> table.efdt[i][j];
id >> table->ef[i][j];
id >> table->efd[i][j];
id >> table->eft[i][j];
id >> table->efdt[i][j];
}
}
//read the number density
for (j=0; j<table.jmax; j++) {
for (i=0; i<table.imax; i++){
for (j=0; j<table->jmax; j++) {
for (i=0; i<table->imax; i++){
getline(helm_table, data);
stringstream id(data);
id >> table.xf[i][j];
id >> table.xfd[i][j];
id >> table.xft[i][j];
id >> table.xfdt[i][j];
id >> table->xf[i][j];
id >> table->xfd[i][j];
id >> table->xft[i][j];
id >> table->xfdt[i][j];
}
}
helm_table.close(); //done reading
// construct the temperature and density deltas and their inverses
for (j=0; j<table.jmax; j++) {
double dth = table.t[j+1] - table.t[j];
for (j=0; j<table->jmax; j++) {
double dth = table->t[j+1] - table->t[j];
double dt2 = dth * dth;
double dti = 1.0/dth;
double dt2i = 1.0/dt2;
table.dt_sav[j] = dth;
table.dt2_sav[j] = dt2;
table.dti_sav[j] = dti;
table.dt2i_sav[j] = dt2i;
table->dt_sav[j] = dth;
table->dt2_sav[j] = dt2;
table->dti_sav[j] = dti;
table->dt2i_sav[j] = dt2i;
}
for (i=0; i<table.imax; i++) {
double dd = table.d[i+1] - table.d[i];
for (i=0; i<table->imax; i++) {
double dd = table->d[i+1] - table->d[i];
double dd2 = dd * dd;
double ddi = 1.0/dd;
table.dd_sav[i] = dd;
table.dd2_sav[i] = dd2;
table.ddi_sav[i] = ddi;
table->dd_sav[i] = dd;
table->dd2_sav[i] = dd2;
table->ddi_sav[i] = ddi;
}
table.loaded = true;
table->loaded = true;
return table;
}

70
src/eos/public/eosIO.h Normal file
View File

@@ -0,0 +1,70 @@
#ifndef EOSIO_H
#define EOSIO_H
#include <string>
#include <variant>
#include <memory>
// EOS table format includes
#include "helm.h"
using EOSTable = std::variant<
std::unique_ptr<helmholtz::HELMTable>
>;
/**
* @class EosIO
* @brief Handles the input/output operations for EOS tables.
*
* The EosIO class is responsible for loading and managing EOS tables from files.
* It supports different formats, currently only HELM format.
*
* Example usage:
* @code
* EosIO eosIO("path/to/file");
* std::string format = eosIO.getFormat();
* EOSTable& table = eosIO.getTable();
* @endcode
*/
class EosIO {
private:
std::string m_filename; ///< The filename of the EOS table.
bool m_loaded = false; ///< Flag indicating if the table is loaded.
std::string m_format; ///< The format of the EOS table.
EOSTable m_table; ///< The EOS table data.
/**
* @brief Loads the EOS table from the file.
*/
void load();
/**
* @brief Loads the HELM format EOS table.
*/
void loadHelm();
public:
/**
* @brief Constructs an EosIO object with the given filename.
* @param filename The filename of the EOS table.
*/
EosIO(const std::string filename);
/**
* @brief Default destructor.
*/
~EosIO() = default;
/**
* @brief Gets the format of the EOS table.
* @return The format of the EOS table as a string.
*/
std::string getFormat() const;
/**
* @brief Gets the EOS table.
* @return A reference to the EOS table.
*/
EOSTable& getTable();
};
#endif // EOSIO_H

View File

@@ -35,6 +35,8 @@
#include <string>
#include <format>
#include "debug.h"
/**
* @brief 2D array template alias.
* @tparam T Type of the array elements.
@@ -139,6 +141,118 @@ namespace helmholtz
heap_deallocate_contiguous_2D_memory(xfdt);
}
// // Delete copy constructor and copy assignment operator to prevent accidental shallow copies
// HELMTable(const HELMTable&) = delete;
// HELMTable& operator=(const HELMTable&) = delete;
// // Move constructor
// HELMTable(HELMTable&& other) noexcept
// : loaded(other.loaded),
// f(other.f), fd(other.fd), ft(other.ft), fdd(other.fdd), ftt(other.ftt), fdt(other.fdt),
// fddt(other.fddt), fdtt(other.fdtt), fddtt(other.fddtt),
// dpdf(other.dpdf), dpdfd(other.dpdfd), dpdft(other.dpdft), dpdfdt(other.dpdfdt),
// ef(other.ef), efd(other.efd), eft(other.eft), efdt(other.efdt),
// xf(other.xf), xfd(other.xfd), xft(other.xft), xfdt(other.xfdt)
// {
// other.f = nullptr;
// other.fd = nullptr;
// other.ft = nullptr;
// other.fdd = nullptr;
// other.ftt = nullptr;
// other.fdt = nullptr;
// other.fddt = nullptr;
// other.fdtt = nullptr;
// other.fddtt = nullptr;
// other.dpdf = nullptr;
// other.dpdfd = nullptr;
// other.dpdft = nullptr;
// other.dpdfdt = nullptr;
// other.ef = nullptr;
// other.efd = nullptr;
// other.eft = nullptr;
// other.efdt = nullptr;
// other.xf = nullptr;
// other.xfd = nullptr;
// other.xft = nullptr;
// other.xfdt = nullptr;
// }
// // Move assignment operator
// HELMTable& operator=(HELMTable&& other) noexcept {
// if (this != &other) {
// // Deallocate current memory
// heap_deallocate_contiguous_2D_memory(f);
// heap_deallocate_contiguous_2D_memory(fd);
// heap_deallocate_contiguous_2D_memory(ft);
// heap_deallocate_contiguous_2D_memory(fdd);
// heap_deallocate_contiguous_2D_memory(ftt);
// heap_deallocate_contiguous_2D_memory(fdt);
// heap_deallocate_contiguous_2D_memory(fddt);
// heap_deallocate_contiguous_2D_memory(fdtt);
// heap_deallocate_contiguous_2D_memory(fddtt);
// heap_deallocate_contiguous_2D_memory(dpdf);
// heap_deallocate_contiguous_2D_memory(dpdfd);
// heap_deallocate_contiguous_2D_memory(dpdft);
// heap_deallocate_contiguous_2D_memory(dpdfdt);
// heap_deallocate_contiguous_2D_memory(ef);
// heap_deallocate_contiguous_2D_memory(efd);
// heap_deallocate_contiguous_2D_memory(eft);
// heap_deallocate_contiguous_2D_memory(efdt);
// heap_deallocate_contiguous_2D_memory(xf);
// heap_deallocate_contiguous_2D_memory(xfd);
// heap_deallocate_contiguous_2D_memory(xft);
// heap_deallocate_contiguous_2D_memory(xfdt);
// // Transfer ownership of resources
// loaded = other.loaded;
// f = other.f;
// fd = other.fd;
// ft = other.ft;
// fdd = other.fdd;
// ftt = other.ftt;
// fdt = other.fdt;
// fddt = other.fddt;
// fdtt = other.fdtt;
// fddtt = other.fddtt;
// dpdf = other.dpdf;
// dpdfd = other.dpdfd;
// dpdft = other.dpdft;
// dpdfdt = other.dpdfdt;
// ef = other.ef;
// efd = other.efd;
// eft = other.eft;
// efdt = other.efdt;
// xf = other.xf;
// xfd = other.xfd;
// xft = other.xft;
// xfdt = other.xfdt;
// // Null out the other object's pointers
// other.f = nullptr;
// other.fd = nullptr;
// other.ft = nullptr;
// other.fdd = nullptr;
// other.ftt = nullptr;
// other.fdt = nullptr;
// other.fddt = nullptr;
// other.fdtt = nullptr;
// other.fddtt = nullptr;
// other.dpdf = nullptr;
// other.dpdfd = nullptr;
// other.dpdft = nullptr;
// other.dpdfdt = nullptr;
// other.ef = nullptr;
// other.efd = nullptr;
// other.eft = nullptr;
// other.efdt = nullptr;
// other.xf = nullptr;
// other.xfd = nullptr;
// other.xft = nullptr;
// other.xfdt = nullptr;
// }
// return *this;
// }
friend std::ostream& operator<<(std::ostream& os, const helmholtz::HELMTable& table) {
if (!table.loaded) {
os << "HELMTable not loaded\n";
@@ -371,7 +485,7 @@ namespace helmholtz
* @param filename Path to the file containing the table.
* @return HELMTable structure containing the table data.
*/
HELMTable read_helm_table(const std::string filename);
std::unique_ptr<HELMTable> read_helm_table(const std::string filename);
/**
* @brief Calculate the Helmholtz EOS components.

View File

@@ -6,14 +6,22 @@ meshIO_sources = files(
meshIO_headers = files(
'public/meshIO.h'
)
dependencies = [
mfem_dep
]
# Define the libmeshIO library so it can be linked against by other parts of the build system
libmeshIO = static_library('meshIO',
meshIO_sources,
include_directories: include_directories('public'),
cpp_args: ['-fvisibility=default'],
dependencies: [mfem_dep],
dependencies: dependencies,
install : true)
meshio_dep = declare_dependency(
include_directories: include_directories('public'),
link_with: libmeshIO,
dependencies: dependencies
)
# Make headers accessible
install_headers(meshIO_headers, subdir : '4DSSE/meshIO')

View File

@@ -26,7 +26,7 @@
#include "meshIO.h"
MeshIO::MeshIO(const std::string &mesh_file)
MeshIO::MeshIO(const std::string mesh_file)
{
mesh_file_ = mesh_file;
std::ifstream mesh_stream(mesh_file);

View File

@@ -39,7 +39,7 @@ public:
* @brief Constructor that initializes the MeshIO object with a mesh file.
* @param mesh_file The name of the mesh file.
*/
MeshIO(const std::string &mesh_file);
MeshIO(const std::string mesh_file);
/**
* @brief Destructor for the MeshIO class.

View File

@@ -1,11 +1,18 @@
# Build resources first so that all the embedded resources are available to the other targets
subdir('resources')
# Build the main source code in the correct order
# Build the main source code
subdir('dobj')
subdir('const')
subdir('opatIO')
subdir('meshIO')
# Utility Libraries
subdir('misc')
subdir('config')
subdir('probe')
subdir('const')
subdir('dobj')
# Asset Libraries
subdir('eos')
subdir('opatIO')
subdir('meshIO')
# Resouce Manager Libraries
subdir('resource')
# Physics Libraries

36
src/misc/macros/debug.h Normal file
View File

@@ -0,0 +1,36 @@
/**
* @file debug.h
* @brief Defines a macro for triggering a breakpoint in different compilers and platforms.
*
* This file provides a macro `BREAKPOINT()` that triggers a breakpoint
* in the debugger, depending on the compiler and platform being used.
*
* Usage:
* @code
* BREAKPOINT(); // Triggers a breakpoint in the debugger
* @endcode
*/
#ifdef __GNUC__ // GCC and Clang
/**
* @brief Triggers a breakpoint in GCC and Clang.
*/
#define BREAKPOINT() __builtin_debugtrap()
#elif defined(_MSC_VER) // MSVC
/**
* @brief Triggers a breakpoint in MSVC.
*/
#define BREAKPOINT() __debugbreak()
#elif defined(__APPLE__) && defined(__MACH__) // macOS with Clang and LLDB
#include <signal.h>
/**
* @brief Triggers a breakpoint in macOS with Clang and LLDB.
*/
#define BREAKPOINT() raise(SIGTRAP)
#else
#include <csignal>
/**
* @brief Triggers a breakpoint in other platforms.
*/
#define BREAKPOINT() std::raise(SIGTRAP)
#endif

View File

@@ -0,0 +1,21 @@
# ***********************************************************************
#
# Copyright (C) 2025 -- The 4D-STAR Collaboration
# File Author: Emily Boudreaux
# Last Modified: March 19, 2025
#
# 4DSSE is free software; you can use it and/or modify
# it under the terms and restrictions the GNU General Library Public
# License version 3 (GPLv3) as published by the Free Software Foundation.
#
# 4DSSE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this software; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# *********************************************************************** #
macros_dep = declare_dependency(include_directories: include_directories('.'))

View File

@@ -0,0 +1,16 @@
#ifndef WARNING_CONTROL_H
#define WARNING_CONTROL_H
#if defined(__GNUC__) || defined(__clang__)
#define DEPRECATION_WARNING_OFF _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define DEPRECATION_WARNING_ON _Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
#define DEPRECATION_WARNING_OFF __pragma(warning(push)) __pragma(warning(disable: 4996))
#define DEPRECATION_WARNING_ON __pragma(warning(pop))
#else
#define DEPRECATION_WARNING_OFF
#define DEPRECATION_WARNING_ON
#endif
#endif // WARNING_CONTROL_H

2
src/misc/meson.build Normal file
View File

@@ -0,0 +1,2 @@
# IMPORTANT: DO NOT MAKE MISC DEPEND ON ANY OTHER MODULE AS IT IS THE FIRST MODULE TO BE BUILT
subdir('macros')

View File

@@ -16,5 +16,9 @@ libopatIO = library('opatIO',
install : true,
)
opatio_dep = declare_dependency(
include_directories: include_directories('public'),
link_with: libopatIO,
)
# Make headers accessible
install_headers(opatIO_headers, subdir : '4DSSE/opatIO')

View File

@@ -56,7 +56,7 @@ T swap_bytes(T value) {
// Constructor
OpatIO::OpatIO() {}
OpatIO::OpatIO(std::string filename) : filename(filename) {
OpatIO::OpatIO(const std::string filename) : filename(filename) {
load();
}

View File

@@ -21,7 +21,6 @@
#ifndef OPATIO_H
#define OPATIO_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

40
src/resource/meson.build Normal file
View File

@@ -0,0 +1,40 @@
# Define the library
resourceManager_sources = files(
'private/resourceManager.cpp',
'private/resourceManagerTypes.cpp'
)
resourceManager_headers = files(
'public/resourceManager.h',
'public/resourceManagerTypes.h'
)
dependencies = [
yaml_cpp_dep,
opatio_dep,
eos_dep,
quill_dep,
config_dep,
probe_dep,
mfem_dep,
macros_dep,
meshio_dep
]
libResourceHeader_dep = declare_dependency(include_directories: include_directories('public'))
# Define the libresourceManager library so it can be linked against by other parts of the build system
libresourceManager = static_library('resourceManager',
resourceManager_sources,
include_directories: include_directories('public'),
cpp_args: ['-fvisibility=default'],
dependencies: dependencies,
install : true)
resourceManager_dep = declare_dependency(
include_directories: include_directories('public'),
link_with: libresourceManager,
dependencies: dependencies
)
# Make headers accessible
install_headers(resourceManager_headers, subdir : '4DSSE/resource')

View File

@@ -0,0 +1,68 @@
#include <iostream>
#include <vector>
#include <string>
#include <filesystem>
#include "quill/LogMacros.h"
#include "resourceManager.h"
#include "resourceManagerTypes.h"
#include "debug.h"
#include "config.h"
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
ResourceManager::ResourceManager() {
std::string defaultDataDir = TOSTRING(DATA_DIR);
m_dataDir = m_config.get<std::string>("Data:Dir", defaultDataDir);
// -- Get the index file path using filesytem to make it a system safe path
std::string indexFilePath = m_dataDir + "/index.yaml";
std::filesystem::path indexFile(indexFilePath);
m_resourceConfig.loadConfig(indexFile.string());
std::vector<std::string> assets = m_resourceConfig.keys();
for (auto key : assets ) {
load(key);
}
}
std::vector<std::string> ResourceManager::getAvaliableResources() {
std::vector<std::string> resources;
resources = m_resourceConfig.keys();
return resources;
}
const Resource& ResourceManager::getResource(const std::string &name) const {
auto it = m_resources.find(name);
if (it != m_resources.end()) {
return it->second;
}
throw std::runtime_error("Resource " + name + " not found");
}
bool ResourceManager::loadResource(std::string& name) {
return load(name);
}
bool ResourceManager::load(const std::string& name) {
const std::string resourcePath = m_dataDir + "/" + m_resourceConfig.get<std::string>(name);
std::filesystem::path resourceFile(resourcePath);
if (!std::filesystem::exists(resourceFile)) {
LOG_ERROR(m_logger, "Resource file not found: {}", resourceFile.string());
return false;
}
LOG_INFO(m_logger, "Loading resource: {}", resourceFile.string());
if (m_resources.find(name) != m_resources.end()) {
LOG_INFO(m_logger, "Resource already loaded: {}", name);
return true;
}
Resource resource = createResource(name, resourcePath);
m_resources[name] = std::move(resource);
// -- Check if the resource is already in the map
return true;
}

View File

@@ -0,0 +1,41 @@
#include <string>
#include "resourceManagerTypes.h"
#include "opatIO.h"
#include "meshIO.h"
#include "eosIO.h"
#include "debug.h"
std::string getFirstSegment(const std::string& input) {
size_t pos = input.find(':');
if (pos == std::string::npos) {
// No colon found, return the entire string
return input;
} else {
// Return substring from start to the position of the first colon
return input.substr(0, pos);
}
}
Resource createResource(const std::string& type, const std::string& path) {
static const std::unordered_map<std::string, std::function<Resource(const std::string&)>> factoryMap = {
{"opac", [](const std::string& p) { return Resource(
std::make_unique<OpatIO>(p));
}},
{"mesh", [](const std::string& p) { return Resource(
std::make_unique<MeshIO>(p));
}},
{"eos", [](const std::string& p) { return Resource(
std::make_unique<EosIO>(p));
}}
// Add more mappings as needed
};
auto it = factoryMap.find(getFirstSegment(type));
if (it != factoryMap.end()) {
return it->second(path);
} else {
throw std::invalid_argument("Unknown resource type: " + type);
}
}

View File

@@ -0,0 +1,115 @@
#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H
#include <vector>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include "resourceManagerTypes.h"
#include "config.h"
#include "probe.h"
#include "quill/LogMacros.h"
/**
* @class ResourceManager
* @brief Manages resources within the application.
*
* The ResourceManager class is responsible for loading, storing, and providing access to resources.
* It follows the Singleton design pattern to ensure only one instance of the manager exists.
*/
class ResourceManager {
private:
/**
* @brief Private constructor to prevent instantiation.
*/
ResourceManager();
/**
* @brief Deleted copy constructor to prevent copying.
*/
ResourceManager(const ResourceManager&) = delete;
/**
* @brief Deleted assignment operator to prevent assignment.
*/
ResourceManager& operator=(const ResourceManager&) = delete;
Config& m_config = Config::getInstance();
Probe::LogManager& m_logManager = Probe::LogManager::getInstance();
quill::Logger* m_logger = m_logManager.getLogger("log");
Config m_resourceConfig;
std::string m_dataDir;
std::unordered_map<std::string, Resource> m_resources;
/**
* @brief Loads a resource by name.
* @param name The name of the resource to load.
* @return True if the resource was loaded successfully, false otherwise.
*/
bool load(const std::string& name);
public:
/**
* @brief Gets the singleton instance of the ResourceManager.
* @return The singleton instance of the ResourceManager.
*/
static ResourceManager& getInstance() {
static ResourceManager instance;
return instance;
}
/**
* @brief Gets a list of available resources.
* @return A vector of strings containing the names of available resources.
*
* Example usage:
* @code
* ResourceManager& manager = ResourceManager::getInstance();
* std::vector<std::string> resources = manager.getAvaliableResources();
* @endcode
*/
std::vector<std::string> getAvaliableResources();
/**
* @brief Gets a resource by name.
* @param name The name of the resource to retrieve.
* @return A constant reference to the requested resource.
* @throws std::runtime_error if the resource is not found.
*
* Example usage:
* @code
* ResourceManager& manager = ResourceManager::getInstance();
* const Resource& resource = manager.getResource("exampleResource");
* @endcode
*/
const Resource& getResource(const std::string &name) const;
/**
* @brief Loads a resource by name.
* @param name The name of the resource to load.
* @return True if the resource was loaded successfully, false otherwise.
*
* Example usage:
* @code
* ResourceManager& manager = ResourceManager::getInstance();
* bool success = manager.loadResource("exampleResource");
* @endcode
*/
bool loadResource(std::string& name);
/**
* @brief Loads all resources.
* @return An unordered map with resource names as keys and load success as values.
*
* Example usage:
* @code
* ResourceManager& manager = ResourceManager::getInstance();
* std::unordered_map<std::string, bool> results = manager.loadAllResources();
* @endcode
*/
std::unordered_map<std::string, bool> loadAllResources();
};
#endif // RESOURCE_MANAGER_H

View File

@@ -0,0 +1,71 @@
#ifndef RESOURCE_MANAGER_TYPES_H
#define RESOURCE_MANAGER_TYPES_H
#include <memory>
#include <variant>
#include "opatIO.h"
#include "helm.h"
#include "meshIO.h"
#include "eosIO.h"
/**
* @file resourceManagerTypes.h
* @brief Defines types and functions for managing resources.
*
* This file provides type definitions and functions for handling different
* types of resources in a unified manner.
*/
// -- Valid resource types
/**
* @brief A variant type that can hold different types of resources.
*
* The Resource type is a std::variant that can hold a unique pointer to
* an OpatIO, MeshIO, or EosIO object.
*
* Example usage:
* @code
* Resource resource = std::make_unique<OpatIO>(...);
* @endcode
*/
using Resource = std::variant<
std::unique_ptr<OpatIO>,
std::unique_ptr<MeshIO>,
std::unique_ptr<EosIO>>;
/**
* @brief Extracts the first segment of a given string.
*
* This function takes a string input and returns the first segment
* separated by a delimiter (default is '/').
*
* @param input The input string to be processed.
* @return The first segment of the input string.
*
* Example usage:
* @code
* std::string segment = getFirstSegment("path/to/resource");
* // segment == "path"
* @endcode
*/
std::string getFirstSegment(const std::string& input);
/**
* @brief Creates a resource based on the specified type and path.
*
* This function creates a resource object based on the provided type
* and initializes it using the given path.
*
* @param type The type of the resource to be created (e.g., "OpatIO", "MeshIO", "EosIO").
* @param path The path to initialize the resource with.
* @return A Resource object initialized with the specified type and path.
*
* Example usage:
* @code
* Resource resource = createResource("OpatIO", "path/to/opat");
* @endcode
*/
Resource createResource(const std::string& type, const std::string& path);
#endif // RESOURCE_MANAGER_TYPES_H

View File

@@ -1,11 +1,12 @@
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <sstream>
#include "helm.h"
#include "resourceManager.h"
#include "config.h"
/**
* @file constTest.cpp
@@ -17,21 +18,20 @@
*/
class eosTest : public ::testing::Test {};
std::string HELM_FILENAME = std::string(getenv("MESON_SOURCE_ROOT")) + "/assets/eos/helm_table.dat";
std::string TEST_CONFIG = std::string(getenv("MESON_SOURCE_ROOT")) + "/tests/testsConfig.yaml";
/**
* @test Verify default constructor initializes correctly.
*/
TEST_F(eosTest, constructor) {
using namespace helmholtz;
EXPECT_NO_THROW(HELMTable table = read_helm_table(HELM_FILENAME));
}
TEST_F(eosTest, read_helm_table) {
using namespace helmholtz;
HELMTable table = read_helm_table(HELM_FILENAME);
// Capture the << operator output as a string
Config::getInstance().loadConfig(TEST_CONFIG);
ResourceManager& rm = ResourceManager::getInstance();
auto& eos = std::get<std::unique_ptr<EosIO>>(rm.getResource("eos:helm"));
auto& table = eos->getTable();
auto& helmTable = *std::get<std::unique_ptr<helmholtz::HELMTable>>(table);
std::stringstream ss;
ss << table;
ss << helmTable;
EXPECT_EQ(ss.str(), "HELMTable Data:\n imax: 541, jmax: 201\n Temperature Range: [1000, 1e+13]\n Density Range: [1e-12, 1e+15]\n");
}
@@ -58,28 +58,31 @@ TEST_F(eosTest, get_helm_EOS) {
eos1.abar = 1.0/asum;
eos1.zbar = eos1.abar*zsum;
HELMTable table = read_helm_table(HELM_FILENAME);
EOS eos = get_helm_EOS(eos1, table);
// std::cout << eos << std::endl;
ResourceManager& rm = ResourceManager::getInstance();
auto& eos = std::get<std::unique_ptr<EosIO>>(rm.getResource("eos:helm"));
auto& table = eos->getTable();
auto& helmTable = *std::get<std::unique_ptr<helmholtz::HELMTable>>(table);
EOS helmEos = get_helm_EOS(eos1, helmTable);
const double absErr = 1e-12;
//Check composition info
EXPECT_DOUBLE_EQ( eos.ye, 8.75e-01);
EXPECT_NEAR( helmEos.ye, 8.75e-01, absErr);
//Check E, P, S and derivatives of each wrt Rho and T
EXPECT_DOUBLE_EQ( eos.etaele, 2.3043348231021554e+01);
EXPECT_DOUBLE_EQ( eos.etot, 1.1586558190936826e+17);
EXPECT_DOUBLE_EQ(eos.denerdd, 6.1893000468285858e+10);
EXPECT_DOUBLE_EQ(eos.denerdt, 1.2129708972542575e+08);
EXPECT_DOUBLE_EQ( eos.ptot, 6.9610135220017030e+22);
EXPECT_DOUBLE_EQ(eos.dpresdd, 1.0296440482849070e+17);
EXPECT_DOUBLE_EQ(eos.dpresdt, 7.7171347517311625e+13);
EXPECT_DOUBLE_EQ( eos.stot, 6.0647461970567346e+08);
EXPECT_DOUBLE_EQ(eos.dentrdd,-7.7171347517311645e+01);
EXPECT_DOUBLE_EQ(eos.dentrdt, 1.2129708972542577e+00);
EXPECT_NEAR( helmEos.etaele, 2.3043348231021554e+01, absErr);
EXPECT_NEAR( helmEos.etot, 1.1586558190936826e+17, 1e3);
EXPECT_NEAR(helmEos.denerdd, 6.1893000468285858e+10, 1e-2);
EXPECT_NEAR(helmEos.denerdt, 1.2129708972542575e+08, 1e-7);
EXPECT_NEAR( helmEos.ptot, 6.9610135220017030e+22, 1e10);
EXPECT_NEAR(helmEos.dpresdd, 1.0296440482849070e+17, 1e3);
EXPECT_NEAR(helmEos.dpresdt, 7.7171347517311625e+13, 1.0);
EXPECT_NEAR( helmEos.stot, 6.0647461970567346e+08, 1e-7);
EXPECT_NEAR(helmEos.dentrdd,-7.7171347517311645e+01, absErr);
EXPECT_NEAR(helmEos.dentrdt, 1.2129708972542577e+00, absErr);
const double abs_err = 1.0e-12;
// Maxwell relations, should always be zero
EXPECT_NEAR( eos.dse, 0, abs_err);
EXPECT_NEAR( eos.dpe, 0, abs_err);
EXPECT_NEAR( eos.dsp, 0, abs_err);
EXPECT_NEAR( helmEos.dse, 0, absErr);
EXPECT_NEAR( helmEos.dpe, 0, absErr);
EXPECT_NEAR( helmEos.dsp, 0, absErr);
}

View File

@@ -11,7 +11,7 @@ foreach test_file : test_sources
test_exe = executable(
exe_name,
test_file,
dependencies: [gtest_dep, eos_dep, gtest_main],
dependencies: [gtest_dep, eos_dep, gtest_main, resourceManager_dep, config_dep],
install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly
)

View File

@@ -1,6 +1,5 @@
#include <gtest/gtest.h>
#include "meshIO.h"
#include <iostream>
#include <string>
#include "mfem.hpp"

View File

@@ -11,6 +11,7 @@ subdir('meshIO')
subdir('config')
subdir('probe')
subdir('eos')
subdir('resource')
# Subdirectories for sandbox tests
subdir('dobj_sandbox')

View File

@@ -0,0 +1,24 @@
# Test files for const
test_sources = [
'resourceManagerTest.cpp',
]
foreach test_file : test_sources
exe_name = test_file.split('.')[0]
message('Building test: ' + exe_name)
# Create an executable target for each test
test_exe = executable(
exe_name,
test_file,
dependencies: [gtest_dep, resourceManager_dep, gtest_main, macros_dep],
include_directories: include_directories('../../src/resource/public'),
install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly
)
# Add the executable as a test
test(
exe_name,
test_exe,
env: ['MESON_SOURCE_ROOT=' + meson.project_source_root(), 'MESON_BUILD_ROOT=' + meson.project_build_root()])
endforeach

View File

@@ -0,0 +1,61 @@
#include <gtest/gtest.h>
#include "resourceManager.h"
#include "config.h"
#include "eosIO.h"
#include "helm.h"
#include "resourceManagerTypes.h"
#include <string>
#include <stdexcept>
#include <vector>
#include <set>
#include "debug.h"
/**
* @file configTest.cpp
* @brief Unit tests for the resourceManager class.
*/
std::string TEST_CONFIG = std::string(getenv("MESON_SOURCE_ROOT")) + "/tests/testsConfig.yaml";
/**
* @brief Test suite for the resourceManager class.
*/
class resourceManagerTest : public ::testing::Test {};
/**
* @brief Test the constructor of the resourceManager class.
*/
TEST_F(resourceManagerTest, constructor) {
Config::getInstance().loadConfig(TEST_CONFIG);
EXPECT_NO_THROW(ResourceManager::getInstance());
}
TEST_F(resourceManagerTest, getAvaliableResources) {
Config::getInstance().loadConfig(TEST_CONFIG);
ResourceManager& rm = ResourceManager::getInstance();
std::vector<std::string> resources = rm.getAvaliableResources();
std::set<std::string> expected = {"eos:helm", "mesh:sphere"};
std::set<std::string> actual(resources.begin(), resources.end());
EXPECT_EQ(expected, actual);
}
TEST_F(resourceManagerTest, getResource) {
Config::getInstance().loadConfig(TEST_CONFIG);
ResourceManager& rm = ResourceManager::getInstance();
std::string name = "eos:helm";
const Resource &r = rm.getResource(name);
// BREAKPOINT();
const auto &eos = std::get<std::unique_ptr<EosIO>>(r);
EXPECT_EQ("helm", eos->getFormat());
EOSTable &table = eos->getTable();
// -- Extract the Helm table from the EOSTable
helmholtz::HELMTable &helmTable = *std::get<std::unique_ptr<helmholtz::HELMTable>>(table);
EXPECT_DOUBLE_EQ(helmTable.f[0][0], -1692098915534.8142);
EXPECT_THROW(rm.getResource("opac:GS98:high:doesNotExist"), std::runtime_error);
}

38
tests/testsConfig.yaml Normal file
View File

@@ -0,0 +1,38 @@
Debug: true
Probe:
GLVis:
Visualization: true
# Host: "10.8.0.14"
Host: "localhost"
Port: 19916
DefaultKeyset: "iimmMMc"
GetRaySolution:
MakeDir: true
Poly:
Solver:
ViewInitialGuess: true
GMRES:
MaxIter: 5000
RelTol: 1.0e-8
AbsTol: 1.0e-10
PrintLevel: 0
Newton:
MaxIter: 200
RelTol: 1.0e-8
AbsTol: 1.0e-10
PrintLevel: 1
Newton:
Output:
1D:
Save: true
Path: "output/Poly/1D/poly.csv"
RaySamples: 1000
RayCoLatitude: 0.0
RayLongitude: 0.0
# THESE ARE ONLY USED BY THE TEST SUITE AND NOT THE MAIN CODE
# ANY OPTIONS NEEDED FOR THE TEST SUITE SHOULD BE PLACED HERE
Tests:
Poly:
Index: 1.1