Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • 18bb18e
  • /
  • Tests
  • /
  • ReadWriteState
  • /
  • ReadWriteStateTests.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge Iframe embedding
swh:1:cnt:d012a93f9a338cc556dfb85b7467a39a5aa7e544
directory badge Iframe embedding
swh:1:dir:cc97f13860b4eff60135e1b1d507cd0013fc5f66

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
ReadWriteStateTests.cpp
#include "SPlisHSPlasH/Common.h"
#include "Simulator/SimulatorBase.h"
#include "SPlisHSPlasH/Simulation.h"
#include "SPlisHSPlasH/TimeManager.h"
#include "Utilities/FileSystem.h"
#include "Utilities/Logger.h"

// Let Catch provide main():
#define CATCH_CONFIG_MAIN

#include "catch.hpp"
#include <SPlisHSPlasH/Vorticity/MicropolarModel_Bender2017.h>
#include <SPlisHSPlasH/Viscosity/Viscosity_Weiler2018.h>


// Enable memory leak detection
#ifdef _DEBUG
#ifndef EIGEN_ALIGN
#define new DEBUG_NEW 
#endif
#endif

using namespace SPH;
using namespace std;

SimulatorBase* base = nullptr;
Real eps = static_cast<Real>(1.0e-9);

struct FluidModelData
{
	std::string m_id;

	std::vector<Real> m_masses;
	std::vector<Vector3r> m_a;
	std::vector<Vector3r> m_v0;
	std::vector<Vector3r> m_x0;
	std::vector<Vector3r> m_x;
	std::vector<Vector3r> m_v;
	std::vector<Real> m_density;
	std::vector<unsigned int> m_particleId;
	std::vector<unsigned int> m_numNeighbors;
	std::vector<ParticleState> m_particleState;
	Real m_V;
	int m_surfaceTensionMethod;
	int m_viscosityMethod;
	int m_vorticityMethod;
	int m_dragMethod;
	int m_elasticityMethod;

	FluidModelData(const FluidModel* fm)
	{
		Simulation* sim = Simulation::getCurrent();
		m_id = fm->getId();
		m_V = fm->getVolume(0);

		auto numParticles = fm->numActiveParticles();
		m_masses.resize(numParticles);
		m_a.resize(numParticles);
		m_v0.resize(numParticles);
		m_x0.resize(numParticles);
		m_x.resize(numParticles);
		m_v.resize(numParticles);
		m_density.resize(numParticles);
		m_particleId.resize(numParticles);
		m_particleState.resize(numParticles);
		m_numNeighbors.resize(numParticles);
		for (auto i = 0u; i < numParticles; i++)
		{
			m_masses[i] = fm->getMass(i);
			m_a[i] = fm->getAcceleration(i);
			m_v0[i] = fm->getVelocity0(i);
			m_x0[i] = fm->getPosition0(i);
			m_x[i] = fm->getPosition(i);
			m_v[i] = fm->getVelocity(i);
			m_density[i] = fm->getDensity(i);
			m_particleId[i] = fm->getParticleId(i);
			m_particleState[i] = fm->getParticleState(i);
			m_numNeighbors[i] = sim->numberOfNeighbors(0, 0, i);
		}

		m_surfaceTensionMethod = fm->getSurfaceTensionMethod();
		m_viscosityMethod = fm->getViscosityMethod();
		m_vorticityMethod= fm->getVorticityMethod();
		m_dragMethod = fm->getDragMethod();
		m_elasticityMethod = fm->getElasticityMethod();
	}
};

struct BoundaryModelData
{
	bool m_sorted;
	unsigned int m_pointSetIndex;
	std::vector<Vector3r> m_x0;
	std::vector<Vector3r> m_x;
	std::vector<Vector3r> m_v;
	std::vector<Real> m_V;

	BoundaryModelData(const BoundaryModel_Akinci2012* bm)
	{
		Simulation* sim = Simulation::getCurrent();
		m_sorted = bm->isSorted();
		m_pointSetIndex = bm->getPointSetIndex();

		auto numParticles = bm->numberOfParticles();
		m_x0.resize(numParticles);
		m_x.resize(numParticles);
		m_v.resize(numParticles);
		m_V.resize(numParticles);
		for (auto i = 0u; i < numParticles; i++)
		{
			m_x0[i] = bm->getPosition0(i);
			m_x[i] = bm->getPosition(i);
			m_v[i] = bm->getVelocity(i);
			m_V[i] = bm->getVolume(i);
		}
	}
};

struct NonpressureData
{
	std::vector<Vector3r> m_omega;
	std::vector<Vector3r> m_vDiff;

	NonpressureData(FluidModel* model)
	{
		auto numParticles = model->numActiveParticles();
		MicropolarModel_Bender2017* micro = static_cast<MicropolarModel_Bender2017*>(model->getVorticityBase());
		Viscosity_Weiler2018* visco = static_cast<Viscosity_Weiler2018*>(model->getViscosityBase());
		m_omega.resize(numParticles);
		m_vDiff.resize(numParticles);
		for (auto i = 0u; i < numParticles; i++)
		{
			m_omega[i] = micro->getAngularVelocity(i);
			m_vDiff[i] = visco->getVDiff(i);
		}
	}
};


bool cmp(const Vector3r& x1, const Vector3r& x2)
{
#ifdef USE_DOUBLE
	return (x1 - x2).norm() < eps;
#else
	return x1 == x2;
#endif
}

void compareStateFluidData(const FluidModelData* f1, const FluidModelData* f2)
{
	auto numParticles = f1->m_x.size();
	auto numParticles2 = f2->m_x.size();
	REQUIRE(numParticles == numParticles2);

	bool chkPos = true;
	bool chkVel = true;
	bool chkId = true;
	for (auto i = 0; i < numParticles; i++)
	{
		if (!cmp(f1->m_x[i], f2->m_x[i]))
			chkPos = false;
		if (!cmp(f1->m_v[i], f2->m_v[i]))
			chkVel = false;
		if (f1->m_particleId[i] != f2->m_particleId[i])
			chkId = false;
	}

	REQUIRE(f1->m_id == f2->m_id);
	REQUIRE(f1->m_surfaceTensionMethod == f2->m_surfaceTensionMethod);
	REQUIRE(f1->m_viscosityMethod == f2->m_viscosityMethod);
	REQUIRE(f1->m_vorticityMethod == f2->m_vorticityMethod);
	REQUIRE(f1->m_dragMethod == f2->m_dragMethod);
	REQUIRE(f1->m_elasticityMethod == f2->m_elasticityMethod);
	REQUIRE(chkPos);
	REQUIRE(chkVel);
	REQUIRE(chkId);
}

void compareStateBoundaryData(const BoundaryModelData* b1, const BoundaryModelData* b2)
{
	auto numParticles = b1->m_x.size();
	auto numParticles2 = b2->m_x.size();
	REQUIRE(numParticles == numParticles2);

	bool chkPos = true;
	bool chkVel = true;
	bool chkPos0 = true;
	bool chkV = true;
	for (auto i = 0; i < numParticles; i++)
	{
		if (!cmp(b1->m_x[i], b2->m_x[i]))
			chkPos = false;
		if (!cmp(b1->m_v[i], b2->m_v[i]))
			chkVel = false;
		if (!cmp(b1->m_x0[i], b2->m_x0[i]))
			chkPos0 = false;
		if (b1->m_V[i] != b2->m_V[i])
			chkV = false;
	}

	REQUIRE(b1->m_sorted == b2->m_sorted);
	REQUIRE(b1->m_pointSetIndex == b2->m_pointSetIndex);
	REQUIRE(chkPos);
	REQUIRE(chkVel);
	REQUIRE(chkPos0);
	REQUIRE(chkV);
}

void compareStateMicropolarData(const NonpressureData* b1, const NonpressureData* b2)
{
	auto numParticles = b1->m_omega.size();
	auto numParticles2 = b2->m_omega.size();
	REQUIRE(numParticles == numParticles2);

	bool chkOmega = true;
	bool chkVDiff = true;
	for (auto i = 0; i < numParticles; i++)
	{
		if (!cmp(b1->m_omega[i], b2->m_omega[i]))
			chkOmega = false;
		if (!cmp(b1->m_vDiff[i], b2->m_vDiff[i]))
			chkVDiff = false;
	}

	REQUIRE(chkOmega);
	REQUIRE(chkVDiff);
}

void compareAdditionalData(const FluidModelData* f1, const FluidModelData* f2)
{
	auto numParticles = f1->m_x.size();
	auto numParticles2 = f2->m_x.size();
	REQUIRE(numParticles == numParticles2);

	bool chkPos0 = true;
	bool chkVel0 = true;
	bool chkDensity = true;
	bool chkNumNeighbors = true;
	for (auto i = 0; i < numParticles; i++)
	{
		if (!cmp(f1->m_x0[i], f2->m_x0[i]))
			chkPos0 = false;
		if (!cmp(f1->m_v0[i], f2->m_v0[i]))
			chkVel0 = false;
		if (f1->m_numNeighbors[i] != f2->m_numNeighbors[i])
			chkNumNeighbors = false;
		if (abs(f1->m_density[i] - f2->m_density[i]) > 1.e-3)
			chkDensity = false;
	}

	REQUIRE(f1->m_id == f2->m_id);
	REQUIRE(f1->m_surfaceTensionMethod == f2->m_surfaceTensionMethod);
	REQUIRE(f1->m_viscosityMethod == f2->m_viscosityMethod);
	REQUIRE(f1->m_vorticityMethod == f2->m_vorticityMethod);
	REQUIRE(f1->m_dragMethod == f2->m_dragMethod);
	REQUIRE(f1->m_elasticityMethod == f2->m_elasticityMethod);
	REQUIRE(chkPos0);
	REQUIRE(chkVel0);
	REQUIRE(chkNumNeighbors);
	REQUIRE(chkDensity);
}

TEST_CASE("Read/Write state file tests", "[read_write_state]")
{
	REPORT_MEMORY_LEAKS;

	// no parallelism
	omp_set_num_threads(1);
	Utilities::logger.activate(false);

	base = new SimulatorBase();

	// init parameters for simulator call
	std::string exePath = Utilities::FileSystem::getProgramPath();
	std::string sceneFile = Utilities::FileSystem::normalizePath(exePath + "/../data/Scenes/ReadWriteStateTest.json");

	int argc = 2;
	char** argv = new char*[2];
	argv[0] = new char[exePath.length()+1];
	strcpy(argv[0], exePath.c_str());

	argv[1] = new char[sceneFile.length()+1];
	strcpy(argv[1], sceneFile.c_str());

	base->init(argc, argv, "SPlisHSPlasH");

	base->setUseGUI(false);
	base->setUseParticleCaching(false);

	base->initSimulation();

	// set parameters
	Simulation* sim = Simulation::getCurrent();
	sim->setValue<int>(Simulation::CFL_METHOD, 0);
	sim->setValue<bool>(Simulation::ENABLE_Z_SORT, false);

	TimeManager::getCurrent()->setTimeStepSize(static_cast<Real>(0.01));

	// perform simulation for 10 steps and save state
	base->getBoundarySimulator()->initBoundaryData();
	for (unsigned int i = 0; i < 5; i++)
		base->timeStepNoGUI();

	base->setValue<Real>(SimulatorBase::PAUSE_AT, 2.342);
	base->setValue<Real>(SimulatorBase::STOP_AT, 5.2334);
	base->setValue<unsigned int>(SimulatorBase::NUM_STEPS_PER_RENDER, 9);
	base->setValue<Real>(SimulatorBase::DATA_EXPORT_FPS, 21.0);
	base->setValue<std::string>(SimulatorBase::PARTICLE_EXPORT_ATTRIBUTES, "velocity;density;factor");
	sim->setValue<Real>(Simulation::CFL_FACTOR, 0.77);
	sim->setValue<Real>(Simulation::CFL_MAX_TIMESTEPSIZE, 0.011);

	std::string stateFile = Utilities::FileSystem::normalizePath(exePath + "/ReadWriteStateTest.bin");
	base->saveState(stateFile);

	// store data
	const Real W_zero = sim->W_zero();
	const bool doPause = base->getValue<bool>(SimulatorBase::PAUSE);
	const Real pauseAt = base->getValue<Real>(SimulatorBase::PAUSE_AT);
	const Real stopAt = base->getValue<Real>(SimulatorBase::STOP_AT);
	const unsigned int numStepsPerRender = base->getValue<unsigned int>(SimulatorBase::NUM_STEPS_PER_RENDER);
	const int renderWalls = base->getValue<int>(SimulatorBase::RENDER_WALLS);
	const bool stateExport = base->getValue<bool>(SimulatorBase::STATE_EXPORT);
	const Real framesPerSecond = base->getValue<Real>(SimulatorBase::DATA_EXPORT_FPS);
	const Real framesPerSecondState = base->getValue<Real>(SimulatorBase::STATE_EXPORT_FPS);
	const std::string particleAttributes = base->getValue<std::string>(SimulatorBase::PARTICLE_EXPORT_ATTRIBUTES);

	const bool sim2D = sim->getValue<bool>(Simulation::SIM_2D);
	const bool enableZSort = sim->getValue<bool>(Simulation::ENABLE_Z_SORT);
	const Real particleRadius = sim->getValue<Real>(Simulation::PARTICLE_RADIUS);
	const Vector3r gravitation(sim->getVecValue<Real>(Simulation::GRAVITATION));
	const int cflMethod = sim->getValue<int>(Simulation::CFL_METHOD);
	const Real cflFactor = sim->getValue<Real>(Simulation::CFL_FACTOR);
	const Real cflMinTimeStepSize = sim->getValue<Real>(Simulation::CFL_MIN_TIMESTEPSIZE);
	const Real cflMaxTimeStepSize = sim->getValue<Real>(Simulation::CFL_MAX_TIMESTEPSIZE);
	const int kernel = sim->getValue<int>(Simulation::KERNEL_METHOD);
	const int gradKernel = sim->getValue<int>(Simulation::GRAD_KERNEL_METHOD);
	const int simulationMethod = sim->getValue<int>(Simulation::SIMULATION_METHOD);
	const int boundaryHandlingMethod = sim->getValue<int>(Simulation::BOUNDARY_HANDLING_METHOD);

	// copy data
	sim->performNeighborhoodSearch();
	sim->getTimeStep()->computeDensities(0);
	FluidModelData* fluidCopy1 = new FluidModelData(sim->getFluidModel(0));
	BoundaryModelData* boundaryCopy1 = new BoundaryModelData(static_cast<BoundaryModel_Akinci2012*>(sim->getBoundaryModel(0)));
	NonpressureData* micropolarCopy1 = new NonpressureData(sim->getFluidModel(0));
	base->cleanup(); 	

	delete base;
	base = nullptr;

	// second run
	base = new SimulatorBase();
	base->init(argc, argv, "SPlisHSPlasH");

	base->setUseGUI(false);

	base->initSimulation();
	sim = Simulation::getCurrent();
	sim->setValue<int>(Simulation::CFL_METHOD, 0);
	sim->setValue<bool>(Simulation::ENABLE_Z_SORT, false);

	base->getBoundarySimulator()->initBoundaryData();
	base->loadState(stateFile);
	sim->getNeighborhoodSearch()->set_radius(sim->getSupportRadius());
	
	sim->performNeighborhoodSearch();
	sim->getTimeStep()->computeDensities(0);

	REQUIRE(abs(TimeManager::getCurrent()->getTimeStepSize() - static_cast<Real>(0.01)) < eps);
	
	FluidModelData* fluidCopy2 = new FluidModelData(sim->getFluidModel(0));
	BoundaryModelData* boundaryCopy2 = new BoundaryModelData(static_cast<BoundaryModel_Akinci2012*>(sim->getBoundaryModel(0)));
	NonpressureData* micropolarCopy2 = new NonpressureData(sim->getFluidModel(0));

	REQUIRE(W_zero == sim->W_zero());

	// compare write/read of state
	{
		compareStateFluidData(fluidCopy1, fluidCopy2);
		compareStateBoundaryData(boundaryCopy1, boundaryCopy2);
		compareStateMicropolarData(micropolarCopy1, micropolarCopy2);
	}

	// compare additional data
	{
		compareAdditionalData(fluidCopy1, fluidCopy2);
	}

	// parameters
	{
		REQUIRE(doPause == base->getValue<bool>(SimulatorBase::PAUSE));
		REQUIRE(pauseAt == base->getValue<Real>(SimulatorBase::PAUSE_AT));
		REQUIRE(stopAt == base->getValue<Real>(SimulatorBase::STOP_AT));
		REQUIRE(numStepsPerRender == base->getValue<unsigned int>(SimulatorBase::NUM_STEPS_PER_RENDER));
		REQUIRE(renderWalls == base->getValue<int>(SimulatorBase::RENDER_WALLS));
		REQUIRE(stateExport == base->getValue<bool>(SimulatorBase::STATE_EXPORT));
		REQUIRE(framesPerSecond == base->getValue<Real>(SimulatorBase::DATA_EXPORT_FPS));
		REQUIRE(framesPerSecondState == base->getValue<Real>(SimulatorBase::STATE_EXPORT_FPS));
		REQUIRE(particleAttributes == base->getValue<std::string>(SimulatorBase::PARTICLE_EXPORT_ATTRIBUTES));

		REQUIRE(sim2D == sim->getValue<bool>(Simulation::SIM_2D));
		REQUIRE(enableZSort == sim->getValue<bool>(Simulation::ENABLE_Z_SORT));
		REQUIRE(particleRadius == sim->getValue<Real>(Simulation::PARTICLE_RADIUS));
		const Vector3r gravitation2(sim->getVecValue<Real>(Simulation::GRAVITATION));
		REQUIRE(gravitation == gravitation2);
		REQUIRE(cflMethod == sim->getValue<int>(Simulation::CFL_METHOD));
		REQUIRE(cflFactor == sim->getValue<Real>(Simulation::CFL_FACTOR));
		REQUIRE(cflMinTimeStepSize == sim->getValue<Real>(Simulation::CFL_MIN_TIMESTEPSIZE));
		REQUIRE(cflMaxTimeStepSize == sim->getValue<Real>(Simulation::CFL_MAX_TIMESTEPSIZE));
		REQUIRE(kernel == sim->getValue<int>(Simulation::KERNEL_METHOD));
		REQUIRE(gradKernel == sim->getValue<int>(Simulation::GRAD_KERNEL_METHOD));
		REQUIRE(simulationMethod == sim->getValue<int>(Simulation::SIMULATION_METHOD));
		REQUIRE(boundaryHandlingMethod == sim->getValue<int>(Simulation::BOUNDARY_HANDLING_METHOD));
	}

	base->cleanup();
	delete base;
	delete fluidCopy1;
	delete fluidCopy2;
	delete [] argv[0];
	delete [] argv[1];
	delete [] argv;
}

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API