### Minimal working example with GUI Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Minimal Python script to run a simulation with a GUI. Requires SPlisHSPlasH installed correctly and scene files in the data directory. ```python import pysplishsplash as sph def main(): base = sph.Exec.SimulatorBase() base.init() gui = sph.GUI.Simulator_GUI_imgui(base) base.setGui(gui) base.run() if __name__ == "__main__": main() ``` -------------------------------- ### FoamGenerator example command Source: https://splishsplash.readthedocs.io/en/latest/FoamGenerator.html Example command to run FoamGenerator with specified start/end frames, radius, foam scale, input and output files. ```bash FoamGenerator -s 1 -e 500 -r 0.025 --foamscale 1000 -i output\DamBreakModelDragons\partio\ParticleData_Fluid_#.bgeo -o output\DamBreakModelDragons\foam\foam_#.bgeo ``` -------------------------------- ### Build and install wheel for development Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Builds a Python wheel and installs it with pip. Run these commands again to update the installation after rebuilding. ```bash cd SPlisHSPlasH python setup.py bdist_wheel pip install -I build/dist/*.whl ``` -------------------------------- ### Install Python bindings via setup.py Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Builds a wheel and installs it. Run from project root. Recommended to use a virtual environment. Additional CMake variables can be appended after bdist_wheel. ```bash git clone https://github.com/InteractiveComputerGraphics/SPlisHSPlasH.git cd SPlisHSPlasH python setup.py bdist_wheel pip install build/dist/*.whl ``` -------------------------------- ### MeshSkinning command line example Source: https://splishsplash.readthedocs.io/en/latest/MeshSkinning.html Example command to run MeshSkinning with a scene file, enabling splitting and overwrite options. The scene file path is provided as an argument. ```bash MeshSkinning --splitting --overwrite --scene ..\data\Scenes\Beam.json ``` -------------------------------- ### VolumeSampling.exe example command Source: https://splishsplash.readthedocs.io/en/latest/VolumeSampling.html Example command to run the VolumeSampling tool with mode 4 (Kugelstadt et al. 2021), input bunny.obj, and output bunny.vtk. ```bash VolumeSampling.exe --mode 4 -i ..\data\models\bunny.obj -o bunny.vtk ``` -------------------------------- ### Install Python bindings directly from git Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Combines all installation steps into one command. Loses incremental rebuild capability; rebuilding requires full project rebuild. ```bash pip install git+https://github.com/InteractiveComputerGraphics/SPlisHSPlasH.git ``` -------------------------------- ### Build and install Python bindings from source Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Builds a wheel and installs the Python bindings. Run from the project root. Optionally append additional CMake variables after 'bdist_wheel'. ```bash git clone https://github.com/InteractiveComputerGraphics/SPlisHSPlasH.git cd SPlisHSPlasH python setup.py bdist_wheel pip install build/dist/pySPlisHSPlasH-2.8.3-cp37-cp37m-win_amd64.whl ``` -------------------------------- ### Run SPHSimulator with a scene file Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Starts the simulator from the command line with a specified scene file. The scene is loaded and the simulation starts when pause mode is disabled. ```bash ./SPHSimulator ../data/Scenes/DoubleDamBreak.json ``` -------------------------------- ### Configuration block example Source: https://splishsplash.readthedocs.io/en/latest/file_format.html Example JSON configuration block for a SPlisHSPlasH scene file, showing general simulation settings and pressure solver parameters (WCSPH, PBF, DFSPH). Note: the WCSPH block is missing a comma after its closing brace in the source. ```json "Configuration": { "pause": true, "sim2D": false, "timeStepSize": 0.001, "numberOfStepsPerRenderUpdate": 2, "particleRadius": 0.025, "simulationMethod": 4, "gravitation": [0.0,-9.81,0], "cflMethod": 1, "cflFactor": 1, "cflMaxTimeStepSize": 0.005, "WCSPH": { "stiffness": 50000, "exponent": 7 } "PBF": { "minIterations": 2, "maxIterations": 100, "maxError": 0.01, "velocityUpdateMethod": 0 }, "DFSPH": { "minIterations": 2, "maxIterations": 100, "maxError": 0.01, "maxIterationsV": 100, "maxErrorV": 0.1, "enableDivergenceSolver": true } } ``` -------------------------------- ### Install Python bindings dependencies and pipx Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Installs Python development packages and pipx for using Python bindings with -DUSE_PYTHON_BINDINGS=On. Ensures a working Python installation is in PATH. ```bash sudo apt install python3-dev python3-pip python3-venv python3 -m pip install pipx python3 -m pipx ensurepath ``` -------------------------------- ### Install SPlisHSPlasH with pip Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Installs the Python bindings using pip. The trailing slash is important to install from the local directory; run from one directory above the cloned source. ```bash pip install SPlisHSPlasH/ ``` -------------------------------- ### Minimal working example without GUI Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Minimal Python script to run a simulation without a GUI. Uses base.init(useGui=False) and sets STOP_AT to 10.0 (float). ```python import pysplishsplash as sph def main(): base = sph.Exec.SimulatorBase() base.init(useGui=False) base.setValueFloat(base.STOP_AT, 10.0) # Important to have the dot to denote a float base.run() if __name__ == "__main__": main() ``` -------------------------------- ### Material configuration example with XSPH, viscosity, and vorticity Source: https://splishsplash.readthedocs.io/en/latest/file_format.html Example JSON block for defining a material with id 'Fluid'. Includes density, particle coloring fields, and nested blocks for XSPH, Standard viscosity, and Bender et al. 2017 vorticity. The 'id' must match FluidBlock, FluidModel, or Emitter to apply the material. ```json { "Materials": [ { "id": "Fluid", "density0": 1000, "colorField": "velocity", "colorMapType": 1, "renderMinValue": 0.0, "renderMaxValue": 5.0, "viscosityMethod": 1, "vorticityMethod": 1, "maxEmitterParticles": 1000, "emitterReuseParticles": false, "emitterBoxMin": [-4.0,-1.0,-4.0], "emitterBoxMax": [0.0,4,4.0], "XSPH": { "xsph": 0.0, "xsphBoundary": 0.0 }, "Standard viscosity": { "viscosity": 0.01 }, "Bender et al. 2017": { "vorticity": 0.15, "viscosityOmega": 0.05, "inertiaInverse": 0.5 } } ] } ``` -------------------------------- ### Viscosity_Weiler2018.cpp source code Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_Viscosity_Viscosity_Weiler2018.cpp.html Full source code of Viscosity_Weiler2018.cpp as displayed in the documentation. It includes the class implementation, parameter setup, and the start of the AVX-optimized matrix-vector product. ```cpp #include "Viscosity_Weiler2018.h" #include "SPlisHSPlasH/TimeManager.h" #include "Utilities/Timing.h" #include "Utilities/Counting.h" #include "SPlisHSPlasH/Simulation.h" #include "SPlisHSPlasH/BoundaryModel_Akinci2012.h" #include "SPlisHSPlasH/BoundaryModel_Koschier2017.h" #include "SPlisHSPlasH/BoundaryModel_Bender2019.h" #include "SPlisHSPlasH/Utilities/MathFunctions.h" using namespace SPH; using namespace GenParam; std::string Viscosity_Weiler2018::METHOD_NAME = "Weiler et al. 2018"; int Viscosity_Weiler2018::VISCOSITY_COEFFICIENT = -1; int Viscosity_Weiler2018::ITERATIONS = -1; int Viscosity_Weiler2018::MAX_ITERATIONS = -1; int Viscosity_Weiler2018::MAX_ERROR = -1; int Viscosity_Weiler2018::VISCOSITY_COEFFICIENT_BOUNDARY = -1; Viscosity_Weiler2018::Viscosity_Weiler2018(FluidModel *model) : NonPressureForceBase(model), m_vDiff() { m_viscosity = static_cast(0.01); m_maxIter = 100; m_maxError = static_cast(0.01); m_iterations = 0; m_boundaryViscosity = 0.0; m_tangentialDistanceFactor = static_cast(0.5); m_vDiff.resize(model->numParticles(), Vector3r::Zero()); model->addField({ "velocity difference", METHOD_NAME, FieldType::Vector3, [&](const unsigned int i) -> Real* { return &m_vDiff[i][0]; }, true }); } Viscosity_Weiler2018::~Viscosity_Weiler2018(void) { m_model->removeFieldByName("velocity difference"); m_vDiff.clear(); } void Viscosity_Weiler2018::initParameters() { NonPressureForceBase::initParameters(); VISCOSITY_COEFFICIENT = createNumericParameter("viscosity", "Viscosity coefficient", &m_viscosity); setGroup(VISCOSITY_COEFFICIENT, "Fluid Model|Viscosity"); setDescription(VISCOSITY_COEFFICIENT, "Coefficient for the viscosity force computation"); RealParameter* rparam = static_cast(getParameter(VISCOSITY_COEFFICIENT)); rparam->setMinValue(0.0); VISCOSITY_COEFFICIENT_BOUNDARY = createNumericParameter("viscosityBoundary", "Viscosity coefficient (Boundary)", &m_boundaryViscosity); setGroup(VISCOSITY_COEFFICIENT_BOUNDARY, "Fluid Model|Viscosity"); setDescription(VISCOSITY_COEFFICIENT_BOUNDARY, "Coefficient for the viscosity force computation at the boundary."); rparam = static_cast(getParameter(VISCOSITY_COEFFICIENT_BOUNDARY)); rparam->setMinValue(0.0); ITERATIONS = createNumericParameter("viscoIterations", "Iterations", &m_iterations); setGroup(ITERATIONS, "Fluid Model|Viscosity"); setDescription(ITERATIONS, "Iterations required by the viscosity solver."); getParameter(ITERATIONS)->setReadOnly(true); MAX_ITERATIONS = createNumericParameter("viscoMaxIter", "Max. iterations (visco)", &m_maxIter); setGroup(MAX_ITERATIONS, "Fluid Model|Viscosity"); setDescription(MAX_ITERATIONS, "Max. iterations of the viscosity solver."); static_cast*>(getParameter(MAX_ITERATIONS))->setMinValue(1); MAX_ERROR = createNumericParameter("viscoMaxError", "Max. visco error", &m_maxError); setGroup(MAX_ERROR, "Fluid Model|Viscosity"); setDescription(MAX_ERROR, "Max. error of the viscosity solver."); rparam = static_cast(getParameter(MAX_ERROR)); rparam->setMinValue(static_cast(1e-6)); } #ifdef USE_AVX void Viscosity_Weiler2018::matrixVecProd(const Real* vec, Real *result, void *userData) { Simulation *sim = Simulation::getCurrent(); Viscosity_Weiler2018 *visco = (Viscosity_Weiler2018*)userData; FluidModel *model = visco->getModel(); const unsigned int numParticles = model->numActiveParticles(); const unsigned int fluidModelIndex = model->getPointSetIndex(); const unsigned int nFluids = sim->numberOfFluidModels(); const unsigned int nBoundaries = sim->numberOfBoundaryModels(); const Real h = sim->getSupportRadius(); const Real h2 = h*h; const Real dt = TimeManager::getCurrent()->getTimeStepSize(); const Real density0 = model->getDensity0(); const Real mu = visco->m_viscosity * density0; const Real mub = visco->m_boundaryViscosity * density0; const Real sphereVolume = static_cast(4.0 / 3.0 * M_PI) * h2*h; Real d = 10.0; if (sim->is2DSimulation()) d = 8.0; const Scalarf8 d_mu_rho0(d * mu * density0); const Scalarf8 d_mub(d * mub); const Scalarf8 h2_001(0.01f*h2); const Scalarf8 density0_avx(density0); ``` -------------------------------- ### void init() Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_debug_tools.html Initializes the DebugTools instance. ```APIDOC ## void init() ### Description Initializes the DebugTools instance. ### Method Member function ### Signature `void init()` ``` -------------------------------- ### FluidBlocks JSON configuration example Source: https://splishsplash.readthedocs.io/en/latest/file_format.html Defines an axis-aligned fluid block with denseMode, start, end, translation, and scale parameters. The denseMode values are 0 (regular), 1 (more dense), and 2 (dense). ```json "FluidBlocks": [ { "denseMode": 0, "start": [-2.0, 0.0, -1], "end": [-0.5, 1.5, 1], "translation": [1.0, 0.0, 0.0], "scale": [1, 1, 1] } ] ``` -------------------------------- ### Emitter::emitParticlesCircle - Circular Emission Setup Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_Emitter.cpp.html Starts the circular emission function. Retrieves time, particle radius, and emission direction. Adjusts emission velocity to a cleanup value when outside the emission time window. Within the emission window, computes the animation margin and circular geometry parameters (height, radius) for particle placement. ```cpp void Emitter::emitParticlesCircle(std::vector &reusedParticles, unsigned int &indexReuse, unsigned int &numEmittedParticles) { TimeManager *tm = TimeManager::getCurrent(); const Real t = tm->getTime(); const Real timeStepSize = tm->getTimeStepSize(); const Vector3r & emitDir = m_rotation.col(0); Simulation *sim = Simulation::getCurrent(); const Real particleRadius = sim->getParticleRadius(); const Real diam = static_cast(2.0)*particleRadius; Vector3r emitVel = m_velocity * emitDir; // shortly before the emitter starts, cleanup the emitter from particles if (t < m_emitStartTime || t > m_emitEndTime) emitVel = emitDir * particleRadius * 10 / 0.25; if (t >= m_emitStartTime - 0.25 && t <= m_emitEndTime) { // animate emitted particles const Vector3r & x0 = m_x; const Real animationMarginAhead = sim->getSupportRadius(); const Vector3r size = getSize(static_cast(m_width), static_cast(m_height), m_type); const Real h = size[0]; const Real r = 0.5f * size[1]; const Real r2 = r * r; const Vector3r pos = x0 + 0.5f * animationMarginAhead * emitDir; } ``` -------------------------------- ### Pressure solve iteration setup Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_IISPH_TimeStepIISPH.cpp.html Sets up a single pressure solve iteration: retrieves simulation data, checks for active particles, and initializes the dij_pj vector for each particle. Uses OpenMP parallelization. ```cpp void TimeStepIISPH::pressureSolveIteration(const unsigned int fluidModelIndex, Real &avg_density_err) { Simulation *sim = Simulation::getCurrent(); FluidModel *model = sim->getFluidModel(fluidModelIndex); const unsigned int numParticles = model->numActiveParticles(); if (numParticles == 0) return; const unsigned int nFluids = sim->numberOfFluidModels(); const unsigned int nBoundaries = sim->numberOfBoundaryModels(); const Real density0 = model->getDensity0(); const Real h = TimeManager::getCurrent()->getTimeStepSize(); const Real h2 = h*h; const Real omega = 0.5; // Compute dij_pj #pragma omp parallel default(shared) { #pragma omp for schedule(static) for (int i = 0; i < (int)numParticles; i++) { Vector3r &dij_pj = m_simulationData.getDij_pj(fluidModelIndex, i); dij_pj.setZero(); const Vector3r &xi = model->getPosition(i); ``` -------------------------------- ### Install Python bindings with pip Source: https://splishsplash.readthedocs.io/en/latest/getting_started.html Clone the SPlisHSPlasH repository and install the Python bindings using pip. It is recommended to use a virtual environment because cache files, models, and scene files are stored in the Python installation directory. ```bash git clone https://github.com/InteractiveComputerGraphics/SPlisHSPlasH.git pip install SPlisHSPlasH/ ``` -------------------------------- ### Install numpy dependency Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Installs numpy, which may be required for the bindings. Future releases may include it as a dependency. ```bash pip install numpy ``` -------------------------------- ### step() Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_surface_tension___becker2007.html Performs a simulation step for the surface tension method. ```APIDOC ## step() ### Description Performs a simulation step for the surface tension method. ### Method virtual void step() ``` -------------------------------- ### Install Ubuntu dependencies for SPlisHSPlasH Source: https://splishsplash.readthedocs.io/en/latest/build_from_source.html Installs required packages for building SPlisHSPlasH on Ubuntu: git, cmake, Xorg development files, freeglut3, and build-essential. ```bash sudo apt install git cmake xorg-dev freeglut3-dev build-essential ``` -------------------------------- ### TimeStepPF Parameter Initialization Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_PF_TimeStepPF.cpp.html Sets up the maxError and stiffness parameters for the projective fluids simulation, including their groups, descriptions, and minimum values. ```cpp MAX_ERROR = createNumericParameter("maxError", "Max. error", &m_maxError); setGroup(MAX_ERROR, "Simulation|Projective Fluids"); setDescription(MAX_ERROR, "Maximal error."); static_cast(getParameter(MAX_ERROR))->setMinValue(static_cast(1e-12)); STIFFNESS = createNumericParameter("stiffness", "Stiffness", &m_stiffness); setGroup(STIFFNESS, "Simulation|Projective Fluids"); setDescription(STIFFNESS, "Stiffness coefficient."); static_cast(getParameter(STIFFNESS))->setMinValue(static_cast(1e-6)); } ``` -------------------------------- ### Setup Material Type Parameter for Elasticity_Kee2023 Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_Elasticity_Elasticity_Kee2023.cpp.html Configures the 'materialType' enum parameter with options 'Stable Neo-Hookean' and 'Co-rotated'. This is part of the Elasticity_Kee2023 class setup. ```C++ MATERIAL_TYPE = createEnumParameter("materialType", "Material type", &m_materialType); setGroup(MATERIAL_TYPE, "Fluid Model|Elasticity"); setDescription(MATERIAL_TYPE, "Constitutive model for the elastic material."); enumParam = static_cast(getParameter(MATERIAL_TYPE)); enumParam->addEnumValue("Stable Neo-Hookean", ENUM_MATERIAL_STABLE_NEOHOOKEAN); enumParam->addEnumValue("Co-rotated", ENUM_MATERIAL_COROTATED); } ``` -------------------------------- ### void EmitterSystem::step() Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_emitter_system.html Advances the emitter system by one simulation step. ```APIDOC ## void EmitterSystem::step() ### Description Advances the emitter system by one simulation step. ``` -------------------------------- ### initKernels Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_simulation.html Initializes the kernel functions used in the simulation. ```APIDOC ## initKernels ### Description Initializes the kernel functions used in the simulation. ### Method `void initKernels()` ``` -------------------------------- ### TimeStepPBF::resize() Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_PBF_TimeStepPBF.cpp.html Initializes the simulation data by calling its init() method. ```cpp void TimeStepPBF::resize() { m_simulationData.init(); } ``` -------------------------------- ### initFactorization Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_elasticity___kugelstadt2021.html Initializes the solver for the linear system by either computing a factorization or loading a factorization from the cache. ```APIDOC ## initFactorization ### Description Initializes the solver for the linear system by either computing a factorization or loading a factorization from the cache. ### Method void initFactorization(std::shared_ptr factorization, std::vector &particleIndices, const unsigned int nFixed, const Real dt, const Real mu) ### Parameters - **factorization** (std::shared_ptr) - Required - The factorization object to use. - **particleIndices** (std::vector&) - Required - Indices of particles involved. - **nFixed** (unsigned int) - Required - Number of fixed particles. - **dt** (Real) - Required - Time step size. - **mu** (Real) - Required - Shear modulus. ### Description Compute the factorization of the linear system matrix. This is only done once at the beginning of the simulation. ``` -------------------------------- ### FluidModels JSON configuration example Source: https://splishsplash.readthedocs.io/en/latest/file_format.html Imports a partio particle file (bunny.bgeo) with translation, rotation axis, rotation angle, and scale. The particleFile can also be an OBJ mesh that is automatically sampled. ```json "FluidModels": [ { "particleFile": "../models/bunny.bgeo", "translation": [-2.0, 0.1, 0.0], "rotationAxis": [0, 1, 0], "rotationAngle": 3.14159265359, "scale": 1 } ] ``` -------------------------------- ### RigidBodies JSON example Source: https://splishsplash.readthedocs.io/en/latest/file_format.html Example JSON configuration for a rigid body in a SplishSplash scene file. It shows a static wall with a box geometry, translation, rotation, scale, color, and sampling mode. The parameters are described in the surrounding documentation. ```json { "RigidBodies": [ { "geometryFile": "../models/UnitBox.obj", "translation": [0,2,0], "rotationAxis": [1, 0, 0], "rotationAngle": 0, "scale": [2.5, 4, 1.0], "color": [0.1, 0.4, 0.6, 1.0], "isDynamic": false, "isWall": true, "mapInvert": true, "mapThickness": 0.0, "mapResolution": [20,20,20], "samplingMode": 1 } ] } ``` -------------------------------- ### setEmitStartTime Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_emitter.html Sets the start time for particle emission. ```APIDOC ## void setEmitStartTime(Real val) ### Description Sets the start time for particle emission. ### Parameters - **val** (Real) - Required - The emission start time. ``` -------------------------------- ### Explicit simulation commands replacing base.run() Source: https://splishsplash.readthedocs.io/en/latest/py_creating_scenes.html Shows the three commands that base.run() is a shortcut for: initSimulation, runSimulation, and cleanup. Use these when you need to change parameters after initialization. ```python base.initSimulation() # init simulation, fluid models, time step, ... base.runSimulation() # start the simulation base.cleanup() # cleanup everything after the simulation ``` -------------------------------- ### setStartTime Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_animation_field.html Sets the start time of the animation field. ```APIDOC ## void setStartTime(Real val) ### Description Sets the start time of the animation field. ### Parameters - **val** (Real) - Required - The start time value. ``` -------------------------------- ### FileSystem.h header with path utilities and makeDir Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_Utilities_FileSystem.h.html Full source of Utilities/FileSystem.h. Provides static methods getFilePath, getFileName, getFileNameWithExt, getFileExt, isRelativePath, and makeDir. Includes platform-specific headers and S_ISDIR/S_ISREG macros. makeDir uses _mkdir on WIN32 and mkdir with S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH elsewhere, returning -1 on failure unless errno is EEXIST. ```cpp #ifndef __FileSystem_h__ #define __FileSystem_h__ #include "StringTools.h" #include "extern/md5/md5.h" #include #ifdef WIN32 #include #define NOMINMAX #include "windows.h" #include #else #include #include #endif #ifdef __APPLE__ #include #endif #ifndef S_ISDIR #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISREG #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif namespace Utilities { class FileSystem { public: static std::string getFilePath(const std::string &path) { std::string npath = normalizePath(path); std::string result = npath; size_t i = result.rfind('.', result.length()); if (i != std::string::npos) { result = result.substr(0, i); } size_t p1 = result.rfind('\\', result.length()); size_t p2 = result.rfind('/', result.length()); if ((p1 != std::string::npos) && (p2 != std::string::npos)) result = result.substr(0, std::max(p1, p2)); else if (p1 != std::string::npos) result = result.substr(0, p1); else if (p2 != std::string::npos) result = result.substr(0, p2); return result; } static std::string getFileName(const std::string &path) { std::string npath = normalizePath(path); std::string result = npath; size_t i = result.rfind('.', result.length()); if (i != std::string::npos) { result = result.substr(0, i); } size_t p1 = result.rfind('\\', result.length()); size_t p2 = result.rfind('/', result.length()); if ((p1 != std::string::npos) && (p2 != std::string::npos)) result = result.substr(std::max(p1, p2) + 1, result.length()); else if (p1 != std::string::npos) result = result.substr(p1 + 1, result.length()); else if (p2 != std::string::npos) result = result.substr(p2 + 1, result.length()); return result; } static std::string getFileNameWithExt(const std::string &path) { std::string npath = normalizePath(path); std::string result = npath; size_t p1 = result.rfind('\\', result.length()); size_t p2 = result.rfind('/', result.length()); if ((p1 != std::string::npos) && (p2 != std::string::npos)) result = result.substr(std::max(p1, p2) + 1, result.length()); else if (p1 != std::string::npos) result = result.substr(p1 + 1, result.length()); else if (p2 != std::string::npos) result = result.substr(p2 + 1, result.length()); return result; } static std::string getFileExt(const std::string &path) { std::string npath = normalizePath(path); std::string result = npath; size_t i = result.rfind('.', result.length()); if (i != std::string::npos) { result = result.substr(i + 1, result.length()); } return result; } static bool isRelativePath(const std::string &path) { std::string npath = normalizePath(path); // Windows size_t i = npath.find(":"); if (i != std::string::npos) return false; else if (npath[0] == '/') return false; return true; } static int makeDir(const std::string &path) { std::string npath = normalizePath(path); struct stat st; int status = 0; if (stat(path.c_str(), &st) != 0) { #if WIN32 status = _mkdir(path.c_str()); #else status = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #endif if (status != 0 && errno != EEXIST) status = -1; } else if (!(S_IFDIR & st.st_mode)) { errno = ENOTDIR; status = -1; } return status; } ``` -------------------------------- ### Example embedded Python script for SplishSplash Source: https://splishsplash.readthedocs.io/en/latest/py_embedded_python.html A complete example script that prints the current simulation time, the position of particle 0, and a counter value in each step. It defines the required init, step, and reset functions, plus two additional commands. ```python import splishsplash as sph import numpy as np counter = 0 function_list = ['command', 'command2'] def init(base): global counter print("init test") counter = 1 def step(): global counter sim = sph.Simulation.getCurrent() fluid = sim.getFluidModel(0) tm = sph.TimeManager.getCurrent() print(fluid.getPosition(0)) print(tm.getTime()) print(counter) counter += 1 print("---") def reset(): print("reset test") def command(): print("tst cmd") def command2(): print("tst cmd2") ``` -------------------------------- ### Show splash help Source: https://splishsplash.readthedocs.io/en/latest/py_getting_started.html Displays the help for the splash command, showing available options and functionality. ```bash splash --help ``` -------------------------------- ### TimeStepDFSPH::pressureSolve() implementation Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_DFSPH_TimeStepDFSPH.cpp.html Full implementation of the DFSPH pressure solver. Computes rho_adv, applies warm start or direct pressure computation, iterates until convergence or max iterations, updates velocities with pressure accelerations, and optionally scales pressure for warm start. ```cpp void TimeStepDFSPH::pressureSolve() { const Real h = TimeManager::getCurrent()->getTimeStepSize(); const Real h2 = h*h; const Real invH = static_cast(1.0) / h; const Real invH2 = static_cast(1.0) / h2; Simulation *sim = Simulation::getCurrent(); const unsigned int nFluids = sim->numberOfFluidModels(); // Compute rho_adv for (unsigned int fluidModelIndex = 0; fluidModelIndex < nFluids; fluidModelIndex++) { FluidModel *model = sim->getFluidModel(fluidModelIndex); const Real density0 = model->getDensity0(); const int numParticles = (int)model->numActiveParticles(); #pragma omp parallel default(shared) { #pragma omp for schedule(static) for (int i = 0; i < numParticles; i++) { // Compute rho_adv,i^(0) (see equation in Section 3.3 in [BK17]) // using the velocities after the non-pressure forces were applied. computeDensityAdv(fluidModelIndex, i, h, density0); // In the end of Section 3.3 [BK17] we have to multiply the density // error with the factor alpha_i divided by h^2. Hence, we multiply // the factor directly by 1/h^2 here. m_simulationData.getFactor(fluidModelIndex, i) *= invH2; // For the warm start we use 0.5 times the old pressure value. // Note: We divide the value by h^2 since we multiplied it by h^2 at the end of // the last time step to make it independent of the time step size. #ifdef USE_WARMSTART if (m_simulationData.getDensityAdv(fluidModelIndex, i) > 1.0) m_simulationData.getPressureRho2(fluidModelIndex, i) = static_cast(0.5) * min(m_simulationData.getPressureRho2(fluidModelIndex, i), static_cast(0.00025)) * invH2; else m_simulationData.getPressureRho2(fluidModelIndex, i) = 0.0; #else // If we don't use a warm start, we directly compute a pressure value // by multiplying the density error with the factor. //m_simulationData.getPressureRho2(fluidModelIndex, i) = 0.0; const Real s_i = static_cast(1.0) - m_simulationData.getDensityAdv(fluidModelIndex, i); const Real residuum = min(s_i, static_cast(0.0)); // r = b - A*p m_simulationData.getPressureRho2(fluidModelIndex, i) = -residuum * m_simulationData.getFactor(fluidModelIndex, i); #endif } } } m_iterations = 0; // Start solver Real avg_density_err = 0.0; bool chk = false; // Perform solver iterations while ((!chk || (m_iterations < m_minIterations)) && (m_iterations < m_maxIterations)) { chk = true; for (unsigned int i = 0; i < nFluids; i++) { FluidModel *model = sim->getFluidModel(i); const Real density0 = model->getDensity0(); avg_density_err = 0.0; pressureSolveIteration(i, avg_density_err); // Maximal allowed density fluctuation const Real eta = m_maxError * static_cast(0.01) * density0; // maxError is given in percent chk = chk && (avg_density_err <= eta); } m_iterations++; } INCREASE_COUNTER("DFSPH - iterations", static_cast(m_iterations)); for (unsigned int fluidModelIndex = 0; fluidModelIndex < nFluids; fluidModelIndex++) { FluidModel *model = sim->getFluidModel(fluidModelIndex); const int numParticles = (int)model->numActiveParticles(); const Real density0 = model->getDensity0(); #pragma omp parallel default(shared) { #pragma omp for schedule(static) for (int i = 0; i < numParticles; i++) { // Time integration of the pressure accelerations to get new velocities computePressureAccel(fluidModelIndex, i, density0, m_simulationData.getPressureRho2Data(), true); model->getVelocity(i) += h * m_simulationData.getPressureAccel(fluidModelIndex, i); } } } #ifdef USE_WARMSTART for (unsigned int fluidModelIndex = 0; fluidModelIndex < nFluids; fluidModelIndex++) { FluidModel* model = sim->getFluidModel(fluidModelIndex); const int numParticles = (int)model->numActiveParticles(); #pragma omp parallel default(shared) { #pragma omp for schedule(static) for (int i = 0; i < numParticles; i++) { // Multiply by h^2, the time step size has to be removed // to make the pressure value independent // of the time step size m_simulationData.getPressureRho2(fluidModelIndex, i) *= h2; } } } #endif } ``` -------------------------------- ### void initModel(RigidBodyObject *rbo) Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_boundary_model___bender2019.html Initializes the boundary model with a rigid body object. ```APIDOC ## void initModel(RigidBodyObject *rbo) ### Description Initializes the boundary model with a rigid body object. ### Method void initModel(RigidBodyObject *rbo) ### Parameters - **rbo** (RigidBodyObject*) - Required - Pointer to the rigid body object. ### Returns None ``` -------------------------------- ### FluidModel::init() Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_fluid_model.html Initializes the fluid model. ```APIDOC ## FluidModel::init() ### Description Initializes the fluid model. ### Method void init() ### Parameters None ### Returns void ``` -------------------------------- ### Elasticity_Kee2023::newtonMatvec (USE_AVX) - start of matrix-vector product Source: https://splishsplash.readthedocs.io/en/latest/api/program_listing_file_SPlisHSPlasH_Elasticity_Elasticity_Kee2023.cpp.html Starts the implementation of the Newton matrix-vector product under the USE_AVX macro. It retrieves particle indices, counts free particles, and obtains references to the AVX vectors p_avx and Ap_avx. The code is incomplete as shown, ending after the variable declarations. ```cpp #ifdef USE_AVX void Elasticity_Kee2023::newtonMatvec(ElasticObject* obj) { const std::vector& group = obj->m_particleIndices; const int numParticles = (int)group.size(); const int nFree = numParticles - (int)obj->m_nFixed; auto& p_avx = obj->m_pcg_p_avx; auto& Ap_avx = obj->m_pcg_Ap_avx; ``` -------------------------------- ### TimeStepMyPressureSolve.cpp - Minimal Implementation for Custom Pressure Solver Source: https://splishsplash.readthedocs.io/en/latest/creating_pressure.html Source file for the custom pressure solver class. It implements the constructor, destructor, step(), and resize() methods. The step() method defines the simulation algorithm and is called by the main loop. ```cpp #include "TimeStepMyPressureSolve.h" using namespace SPH; using namespace GenParam; TimeStepMyPressureSolve::TimeStepMyPressureSolve() : TimeStep() { [...] } TimeStepMyPressureSolve::~TimeStepMyPressureSolve(void) { [...] } void TimeStepMyPressureSolve::step() { [...] } void TimeStepMyPressureSolve::resize() { [...] } ``` -------------------------------- ### SPH::AnimationField::setStartTime Source: https://splishsplash.readthedocs.io/en/latest/genindex.html Sets the start time for the animation field. ```APIDOC ## SPH::AnimationField::setStartTime ### Description Sets the start time for the animation field. ### Method C++ function ### Signature `void SPH::AnimationField::setStartTime(Real startTime)` ### Parameters - `startTime` (Real) - Required - The start time value. ``` -------------------------------- ### setNumActiveParticles0 Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_fluid_model.html Sets the number of active particles at the start of the simulation step. ```APIDOC ## setNumActiveParticles0(unsigned int val) ### Description Sets the number of active particles at the start of the simulation step. ### Method C++ member function (inline) ### Signature `inline void setNumActiveParticles0(unsigned int val)` ### Parameters - **val** (unsigned int) - Required - The new number of active particles at the start of the step. ``` -------------------------------- ### Simulation.cpp: Handle new pressure solver in setSimulationMethod Source: https://splishsplash.readthedocs.io/en/latest/creating_pressure.html Adds a branch in Simulation::setSimulationMethod(...) to instantiate the new TimeStepMyPressureSolver, initialize it, and set the desired standard SPH kernel and gradient kernel. ```cpp else if (method == SimulationMethods::MyPressureSolver) { m_timeStep = new TimeStepMyPressureSolver(); m_timeStep->init(); setValue(Simulation::KERNEL_METHOD, ); setValue(Simulation::GRAD_KERNEL_METHOD, ); } ``` -------------------------------- ### getNumActiveParticles0 Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_fluid_model.html Returns the number of active particles at the start of the simulation step. ```APIDOC ## getNumActiveParticles0() const ### Description Returns the number of active particles at the start of the simulation step. ### Method C++ member function (inline, const) ### Signature `inline unsigned int getNumActiveParticles0() const` ### Returns - **unsigned int** - The number of active particles at the start of the step. ``` -------------------------------- ### void step() Source: https://splishsplash.readthedocs.io/en/latest/api/class_s_p_h_1_1_debug_tools.html Performs a simulation step for debugging purposes. ```APIDOC ## void step() ### Description Performs a simulation step for debugging purposes. ### Method Member function ### Signature `void step()` ```