Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctness testing with TOML #1682

Merged
merged 12 commits into from
Nov 3, 2023
18 changes: 13 additions & 5 deletions src/classes/serializablePairPotential.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

#include "classes/serializablePairPotential.h"

SerializablePairPotential::SerializablePairPotential(double &range, double &delta, bool &source,
std::vector<std::shared_ptr<AtomType>> &types)
: range_(range), delta_(delta), atomTypeChargeSource_(source), atomTypes_(types),
coulombTruncationScheme_(PairPotential::coulombTruncationScheme_),
SerializablePairPotential::SerializablePairPotential(double &range, double &delta, bool &source, bool &forceCharge,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need the SerializablePairPotential class? It feels like its just wrapping functionality that could be added into Dissolve::serialise() and Dissolve::deserialise()...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we need to review SerializablePairPotential, as I'm increasingly unhappy with the design. However, I'm not sure that Dissolve is the right place for it, either. I'll add an issue for it and we can review that before the final TOML addition.

bool &autoCharge, std::vector<std::shared_ptr<AtomType>> &types)
: range_(range), delta_(delta), atomTypeChargeSource_(source), atomTypes_(types), forceCharge_(forceCharge),
autoCharge_(autoCharge), coulombTruncationScheme_(PairPotential::coulombTruncationScheme_),
shortRangeTruncationScheme_(PairPotential::shortRangeTruncationScheme_){};

double &SerializablePairPotential::range() { return range_; }
Expand Down Expand Up @@ -43,9 +43,15 @@ SerialisedValue SerializablePairPotential::serialise() const
SerialisedValue pairPotentials = {
{"range", range_},
{"delta", delta_},
{"includeCoulomb", atomTypeChargeSource_},
{"autoChargeSource", autoCharge_},
{"coulombTruncation", PairPotential::coulombTruncationSchemes().serialise(coulombTruncationScheme_)},
{"shortRangeTruncation", PairPotential::shortRangeTruncationSchemes().serialise(shortRangeTruncationScheme_)}};
if (!autoCharge_)
pairPotentials["autoChargeSource"] = false;
if (forceCharge_)
pairPotentials["forceChargeSource"] = true;
if (atomTypeChargeSource_)
pairPotentials["includeCoulomb"] = true;
for (auto &atomType : atomTypes_)
pairPotentials["atomTypes"][atomType->name().data()] = atomType->serialise();
return pairPotentials;
Expand All @@ -57,6 +63,8 @@ void SerializablePairPotential::deserialise(const SerialisedValue &node)
range_ = toml::find_or<double>(node, "range", 15.0);
delta_ = toml::find_or<double>(node, "delta", 0.005);
atomTypeChargeSource_ = toml::find_or<bool>(node, "includeCoulomb", false);
forceCharge_ = toml::find_or<bool>(node, "forceChargeSource", false);
autoCharge_ = toml::find_or<bool>(node, "autoChargeSource", true);

coulombTruncationScheme_ =
PairPotential::coulombTruncationSchemes().deserialise(toml::find_or<std::string>(node, "coulombTruncation", "Shifted"));
Expand Down
5 changes: 3 additions & 2 deletions src/classes/serializablePairPotential.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SerializablePairPotential : public Serialisable<>
private:
double &range_;
double &delta_;
bool &atomTypeChargeSource_;
bool &atomTypeChargeSource_, &forceCharge_, &autoCharge_;

std::vector<std::shared_ptr<AtomType>> &atomTypes_;

Expand All @@ -24,7 +24,8 @@ class SerializablePairPotential : public Serialisable<>

// AtomTypes
public:
SerializablePairPotential(double &range, double &delta, bool &source, std::vector<std::shared_ptr<AtomType>> &types);
SerializablePairPotential(double &range, double &delta, bool &source, bool &forceCharge, bool &autoCharge,
std::vector<std::shared_ptr<AtomType>> &types);

double &range();
const double &range() const;
Expand Down
4 changes: 2 additions & 2 deletions src/main/dissolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include "classes/species.h"

Dissolve::Dissolve(CoreData &coreData)
: coreData_(coreData),
serializablePairPotential_(pairPotentialRange_, pairPotentialDelta_, atomTypeChargeSource_, coreData_.atomTypes())
: coreData_(coreData), serializablePairPotential_(pairPotentialRange_, pairPotentialDelta_, atomTypeChargeSource_,
forceChargeSource_, automaticChargeSource_, coreData_.atomTypes())
{
// Set core simulation variables
restartFileFrequency_ = 10;
Expand Down
13 changes: 0 additions & 13 deletions src/main/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,6 @@ SerialisedValue Dissolve::serialise() const
{
SerialisedValue root;

// If TOML is disabled,
if constexpr (!toml_testing_flag)
{
Messenger::error("This build does not support TOML.");
return root;
}

if (!coreData_.masterBonds().empty() || !coreData_.masterAngles().empty() || !coreData_.masterTorsions().empty() ||
!coreData_.masterImpropers().empty())
root["master"] = coreData_.serialiseMaster();
Expand All @@ -152,12 +145,6 @@ SerialisedValue Dissolve::serialise() const
// Read values from a serialisable value
void Dissolve::deserialise(const SerialisedValue &node)
{
// If TOML is disabled,
if constexpr (!toml_testing_flag)
{
Messenger::error("This build does not support TOML.");
return;
}

if (node.contains("pairPotentials"))
{
Expand Down
10 changes: 5 additions & 5 deletions tests/modules/epsr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class EPSRModuleTest : public ::testing::Test

TEST_F(EPSRModuleTest, Water3NInpA)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/epsr-water-inpa.txt"));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/epsr-water-inpa.txt"));
ASSERT_TRUE(systemTest.dissolve().iterate(1));

// Estimated Partials
Expand Down Expand Up @@ -107,7 +107,7 @@ TEST_F(EPSRModuleTest, Water3NInpA)

TEST_F(EPSRModuleTest, Water3NX)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/epsr-water-3n-x.txt"));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/epsr-water-3n-x.txt"));
ASSERT_TRUE(systemTest.dissolve().iterate(1));

// Test total neutron-weighted F(r)
Expand Down Expand Up @@ -138,7 +138,7 @@ TEST_F(EPSRModuleTest, Water3NX)

TEST_F(EPSRModuleTest, Benzene)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/epsr-benzene-3n.txt"));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/epsr-benzene-3n.txt"));
ASSERT_TRUE(systemTest.dissolve().iterate(1));

// Test total neutron-weighted F(r)
Expand Down Expand Up @@ -200,7 +200,7 @@ TEST_F(EPSRModuleTest, BenzeneReadPCof) { ASSERT_NO_THROW(systemTest.setUp("diss

TEST_F(EPSRModuleTest, ScatteringMatrix)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/epsr-5datasets.txt"));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/epsr-5datasets.txt"));
ASSERT_TRUE(systemTest.dissolve().iterate(1));

// Find EPSR module
Expand All @@ -221,7 +221,7 @@ TEST_F(EPSRModuleTest, ScatteringMatrix)

TEST_F(EPSRModuleTest, DataWeighting)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/epsr-5datasets-weighted.txt"));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/epsr-5datasets-weighted.txt"));
ASSERT_TRUE(systemTest.dissolve().iterate(1));

// Find EPSR module
Expand Down
4 changes: 2 additions & 2 deletions tests/modules/siteRDF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ TEST_F(SiteRDFModuleTest, WaterDynamic)

TEST_F(SiteRDFModuleTest, WaterFragments)
{
ASSERT_NO_THROW(systemTest.setUp("dissolve/input/siteRDF-waterFragments.txt"));
ASSERT_TRUE(systemTest.iterateRestart(95));
ASSERT_NO_THROW(systemTest.setUp<TomlFailure>("dissolve/input/siteRDF-waterFragments.txt"));
ASSERT_TRUE(systemTest.iterateRestart<TomlFailure>(95));

// O-O RDF
EXPECT_TRUE(systemTest.checkData1D(
Expand Down
99 changes: 68 additions & 31 deletions tests/testData.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,47 +84,84 @@ class DissolveSystemTest
// Set up simulation ready for running, calling any additional setup function if already set
template <int flags = 0> void setUp(std::string_view inputFile)
{

dissolve_.clear();
if (!dissolve_.loadInput(inputFile))
throw(std::runtime_error(fmt::format("Input file '{}' failed to load correctly.\n", inputFile)));
if (rewriteCheck_)
if constexpr (Dissolve::toml_testing_flag || !(flags & TomlFailure))
{
auto newInput = fmt::format("{}/TestOutput_{}.{}.rewrite", DissolveSys::beforeLastChar(inputFile, '/'),
DissolveSys::afterLastChar(inputFile, '/'),
::testing::UnitTest::GetInstance()->current_test_info()->name());
if (!dissolve_.saveInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to rewrite correctly.\n", inputFile)));

dissolve_.clear();
if (!dissolve_.loadInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to reload correctly.\n", newInput)));
}
SerialisedValue toml;
{
CoreData otherCoreData;
Dissolve otherDissolve{otherCoreData};

if (!otherDissolve.loadInput(inputFile))
throw(std::runtime_error(fmt::format("Input file '{}' failed to load correctly.\n", inputFile)));
if (rewriteCheck_)
{
auto newInput = fmt::format("{}/TestOutput_{}.{}.rewrite", DissolveSys::beforeLastChar(inputFile, '/'),
DissolveSys::afterLastChar(inputFile, '/'),
::testing::UnitTest::GetInstance()->current_test_info()->name());
if (!otherDissolve.saveInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to rewrite correctly.\n", inputFile)));

otherDissolve.clear();
if (!otherDissolve.loadInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to reload correctly.\n", newInput)));
}

// Run any other additional setup functions
if (additionalSetUp_)
additionalSetUp_(otherDissolve, otherCoreData);

if (!otherDissolve.prepare())
throw(std::runtime_error("Failed to prepare simulation.\n"));

toml = otherDissolve.serialise();
}

dissolve_.deserialise(toml);
dissolve_.setInputFilename(std::string(inputFile));
auto repeat = dissolve_.serialise();

// Run any other additional setup functions
if (additionalSetUp_)
additionalSetUp_(dissolve_, coreData_);
// Run any other additional setup functions
if (additionalSetUp_)
additionalSetUp_(dissolve_, coreData_);

if (!dissolve_.prepare())
throw(std::runtime_error("Failed to prepare simulation.\n"));
if (!dissolve_.prepare())
throw(std::runtime_error("Failed to prepare simulation.\n"));

if (dissolve_.toml_testing_flag || !(flags & TomlFailure))
compareToml("", toml, repeat);
}
else
{
auto toml = dissolve_.serialise();
if (!dissolve_.loadInput(inputFile))
throw(std::runtime_error(fmt::format("Input file '{}' failed to load correctly.\n", inputFile)));
if (rewriteCheck_)
{
auto newInput = fmt::format("{}/TestOutput_{}.{}.rewrite", DissolveSys::beforeLastChar(inputFile, '/'),
DissolveSys::afterLastChar(inputFile, '/'),
::testing::UnitTest::GetInstance()->current_test_info()->name());
if (!dissolve_.saveInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to rewrite correctly.\n", inputFile)));

dissolve_.clear();
if (!dissolve_.loadInput(newInput))
throw(std::runtime_error(fmt::format("Input file '{}' failed to reload correctly.\n", newInput)));
}

CoreData other_;
Dissolve trial_{other_};
// Run any other additional setup functions
if (additionalSetUp_)
additionalSetUp_(dissolve_, coreData_);

trial_.deserialise(toml);
trial_.setInputFilename(std::string(inputFile));
auto repeat = trial_.serialise();
compareToml("", toml, repeat);
if (!dissolve_.prepare())
throw(std::runtime_error("Failed to prepare simulation.\n"));
}
}
void setUp(std::string_view inputFile, const std::function<void(Dissolve &D, CoreData &C)> &additionalSetUp,
bool known_toml_failure = false)

template <int flags = 0>
void setUp(std::string_view inputFile, const std::function<void(Dissolve &D, CoreData &C)> &additionalSetUp)
{
additionalSetUp_ = additionalSetUp;
setUp(inputFile);
setUp<flags>(inputFile);
}
// Load restart file
void loadRestart(std::string_view restartFile)
Expand All @@ -138,7 +175,7 @@ class DissolveSystemTest
*/
public:
// Iterate for set number of steps but chunked into smaller runs to test restart capability
bool iterateRestart(const int nIterations, const int chunkSize = 20)
template <int flags = 0> bool iterateRestart(const int nIterations, const int chunkSize = 20)
{
// Set the restart file frequency, and grab the input and restart filenames
dissolve_.setRestartFileFrequency(chunkSize);
Expand All @@ -160,7 +197,7 @@ class DissolveSystemTest
if (iterationsDone != nIterations)
{
fmt::print("Resetting at iteration {}...\n", iterationsDone);
setUp(inputFile);
setUp<flags>(inputFile);
loadRestart(restartFile);
}
}
Expand Down
Loading