feat: add PhreeqcKnobs class for managing knob parameters; update CMakeLists.txt and add tests

This commit is contained in:
Max Lübke 2024-12-03 07:48:52 +00:00
parent 288854eb8a
commit 1714132b49
5 changed files with 200 additions and 0 deletions

View File

@ -1,6 +1,7 @@
set(POET_SOURCE_FILES
src/Engine.cpp
src/Runner.cpp
src/Knobs.cpp
#Wrappers
src/Wrapper/EquilibriumWrapper.cpp
src/Wrapper/EquilibriumCompWrapper.cpp
@ -35,6 +36,7 @@ if (BUILD_TESTING AND STANDALONE_BUILD)
test/testPhreeqcEngine.cpp
test/testPhreeqcMatrix.cpp
test/testPhreeqcRunner.cpp
test/testPhreeqcKnobs.cpp
test/utils.cpp
)

View File

@ -0,0 +1,89 @@
#pragma once
#include "Phreeqc.h"
#include <cstdint>
/**
* @brief A struct to hold the parameters for PhreeqcKnobs.
*
* @note See more information on the parameters in the [Phreeqc
* manual](https://wwwbrr.cr.usgs.gov/projects/GWC_coupled/phreeqc/html/final-46.html)
*/
struct PhreeqcKnobsParams {
//
std::uint32_t iterations;
double convergence_tolerance;
double tolerance;
double step_size;
double pe_step_size;
bool diagonal_scale;
};
/**
* @class PhreeqcKnobs
* @brief A class to manage and manipulate knobs (parameters) for a Phreeqc
* instance.
*
* This class provides functionalities to read and write knobs (parameters) for
* a given Phreeqc instance. It also allows getting and setting the parameters
* through accessor and mutator methods.
*
* @note The class supports default copy and move constructors and assignment
* operators.
*
* @param pqc_instance A pointer to a Phreeqc instance.
*/
class PhreeqcKnobs {
public:
/**
* @brief Constructs a PhreeqcKnobs object from an exisiting phreeqc instance
*
* @param pqc_instance A pointer to an instance of the Phreeqc class.
*/
PhreeqcKnobs(Phreeqc *pqc_instance);
PhreeqcKnobs(const PhreeqcKnobs &) = default;
PhreeqcKnobs(PhreeqcKnobs &&) = default;
PhreeqcKnobs &operator=(const PhreeqcKnobs &) = default;
PhreeqcKnobs &operator=(PhreeqcKnobs &&) = default;
/**
* @brief Reads and store the configuration knobs from the given Phreeqc
* instance in the object.
*
* @param pqc_instance A pointer to the Phreeqc instance for which the knobs
* are to be read.
*/
void readKnobs(Phreeqc *pqc_instance);
/**
* @brief Writes the current state of the knobs to the given Phreeqc
* instance.
*
* @param pqc_instance A pointer to the Phreeqc instance whose knobs are to be
* written.
*/
void writeKnobs(Phreeqc *pqc_instance) const;
/**
* @brief Retrieves the current PhreeqcKnobs parameters.
*
* @return PhreeqcKnobsParams The current parameters of the PhreeqcKnobs.
*/
PhreeqcKnobsParams getParams() const { return _params; }
/**
* @brief Sets the parameters for PhreeqcKnobs.
*
* This function assigns the provided PhreeqcKnobsParams object to the
* internal _params member variable, updating the configuration of the
* PhreeqcKnobs instance.
*
* @param params The PhreeqcKnobsParams object containing the new parameters
* to be set.
*/
void setParams(const PhreeqcKnobsParams &params) { _params = params; }
private:
PhreeqcKnobsParams _params;
};

24
poet/src/Knobs.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "PhreeqcKnobs.hpp"
PhreeqcKnobs::PhreeqcKnobs(Phreeqc *pqc_instance) {
this->readKnobs(pqc_instance);
}
void PhreeqcKnobs::readKnobs(Phreeqc *pqc_instance) {
this->_params.iterations = pqc_instance->itmax;
this->_params.convergence_tolerance = pqc_instance->convergence_tolerance;
this->_params.tolerance = pqc_instance->ineq_tol;
this->_params.step_size = pqc_instance->step_size;
this->_params.pe_step_size = pqc_instance->pe_step_size;
this->_params.diagonal_scale =
static_cast<bool>(pqc_instance->diagonal_scale);
}
void PhreeqcKnobs::writeKnobs(Phreeqc *pqc_instance) const {
pqc_instance->itmax = this->_params.iterations;
pqc_instance->convergence_tolerance = this->_params.convergence_tolerance;
pqc_instance->ineq_tol = this->_params.tolerance;
pqc_instance->step_size = this->_params.step_size;
pqc_instance->pe_step_size = this->_params.pe_step_size;
pqc_instance->diagonal_scale = this->_params.diagonal_scale;
}

View File

@ -0,0 +1,84 @@
#include <gtest/gtest.h>
#include <testInput.hpp>
#include "IPhreeqc.hpp"
#include "PhreeqcKnobs.hpp"
#include "utils.hpp"
const std::string barite_db = readFile(barite_test::database);
const std::string barite_script = readFile(barite_test::script);
const std::string knob_input = R"(
KNOBS
-iterations 120
-convergence_tolerance 1e-12
-tolerance 1e-16
-step_size 200
-pe_step_size 20
-diagonal_scale true
END
)";
POET_TEST(PhreeqcKnobsDefaultParams) {
IPhreeqc pqc;
pqc.LoadDatabaseString(barite_db.c_str());
pqc.RunString(barite_script.c_str());
PhreeqcKnobs knobs(pqc.GetPhreeqcPtr());
const PhreeqcKnobsParams params = knobs.getParams();
EXPECT_EQ(params.iterations, 100);
EXPECT_DOUBLE_EQ(params.convergence_tolerance, 1e-8);
EXPECT_DOUBLE_EQ(params.tolerance, 1e-15);
EXPECT_DOUBLE_EQ(params.step_size, 100);
EXPECT_DOUBLE_EQ(params.pe_step_size, 10);
EXPECT_FALSE(params.diagonal_scale);
}
inline void compare_params(const PhreeqcKnobsParams &params) {
EXPECT_EQ(params.iterations, 120);
EXPECT_DOUBLE_EQ(params.convergence_tolerance, 1e-12);
EXPECT_DOUBLE_EQ(params.tolerance, 1e-16);
EXPECT_DOUBLE_EQ(params.step_size, 200);
EXPECT_DOUBLE_EQ(params.pe_step_size, 20);
EXPECT_TRUE(params.diagonal_scale);
}
POET_TEST(PhreeqcKnobsSetFromScript) {
IPhreeqc pqc;
pqc.LoadDatabaseString(barite_db.c_str());
pqc.RunString(knob_input.c_str());
pqc.RunString(barite_script.c_str());
PhreeqcKnobs knobs(pqc.GetPhreeqcPtr());
const PhreeqcKnobsParams params = knobs.getParams();
compare_params(params);
}
POET_TEST(PhreeqcKnobsSetFromClass) {
IPhreeqc pqc;
pqc.LoadDatabaseString(barite_db.c_str());
pqc.RunString(knob_input.c_str());
pqc.RunString(barite_script.c_str());
PhreeqcKnobs knobs(pqc.GetPhreeqcPtr());
IPhreeqc new_instance;
new_instance.LoadDatabaseString(barite_db.c_str());
new_instance.RunString(barite_script.c_str());
knobs.writeKnobs(new_instance.GetPhreeqcPtr());
PhreeqcKnobs new_knobs(new_instance.GetPhreeqcPtr());
const PhreeqcKnobsParams params = new_knobs.getParams();
compare_params(params);
}

View File

@ -1856,6 +1856,7 @@ protected:
friend class IPhreeqcMMS;
friend class IPhreeqcPhast;
friend class PhreeqcRM;
friend class PhreeqcKnobs;
std::vector<int> keycount; // used to mark keywords that have been read