iMSTK
Interactive Medical Simulation Toolkit
imstkSphModel.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkDynamicalModel.h"
10 #include "imstkSphState.h"
11 #include "imstkSPHKernels.h"
12 #include "imstkNeighborSearch.h"
13 #include "imstkSphBoundaryConditions.h"
14 
15 namespace imstk
16 {
17 class PointSet;
18 
25 {
26 private:
27  void initialize();
28 
29 public:
30  SphModelConfig(const double particleRadius);
31  SphModelConfig(const double particleRadius, const double speedOfSound, const double restDensity);
32 
34  double m_minTimestep = 1.0e-6;
35  double m_maxTimestep = 1.0e-3;
36  double m_cflFactor = 1.0;
37 
38  // particle parameters
39  double m_particleRadius = 0.0;
40  double m_particleRadiusSqr = 0.0;
41 
42  // material parameters
43  double m_restDensity = 1000.0;
44  double m_restDensitySqr = 1000000.0;
45  double m_restDensityInv = 1.0 / 1000.0;
46  double m_particleMass = 1.0;
47  double m_particleMassScale = 1.0;
48  double m_eta = 0.5;
49 
50  bool m_bNormalizeDensity = false;
51  bool m_bDensityWithBoundary = false;
52 
53  // pressure
54  double m_pressureStiffness = 50000.0;
55 
56  // viscosity and surface tension/cohesion
57  double m_dynamicViscosityCoeff = 1.0e-2;
58  double m_viscosityBoundary = 1.0e-5;
59  double m_surfaceTensionStiffness = 1.0;
60  double m_frictionBoundary = 0.1;
61 
62  // kernel properties
63  double m_kernelOverParticleRadiusRatio = 4.0;
64  double m_kernelRadius;
66 
67  // gravity
68  Vec3d m_gravity = Vec3d(0.0, -9.81, 0.0);
69 
70  // sound speed
71  double m_speedOfSound = 18.7;
72 
73  // neighbor search
74  NeighborSearch::Method m_neighborSearchMethod = NeighborSearch::Method::UniformGridBasedSearch;
75 };
76 
81 class SphModel : public DynamicalModel<SphState>
82 {
83 public:
84  SphModel();
85  ~SphModel() override = default;
86 
90  void configure(const std::shared_ptr<SphModelConfig>& params) { m_modelParameters = params; }
91 
95  bool initialize() override;
96 
100  void resetToInitialState() override { this->m_currentState->setState(this->m_initialState); }
101 
105  const std::shared_ptr<SphModelConfig>& getParameters() const
106  {
107  assert(m_modelParameters);
108  return m_modelParameters;
109  }
110 
115  void setTimeStep(const double timeStep) override { setDefaultTimeStep(timeStep); }
116 
121  void setDefaultTimeStep(const double timeStep) { m_defaultDt = timeStep; }
122 
126  double getTimeStep() const override { return m_dt; }
127 
128  void setInitialVelocities(const size_t numParticles, const Vec3d& initialVelocities);
129 
130  double getParticlePressure(const double density);
131 
136  void findNearestParticleToVertex(const VecDataArray<double, 3>& points, const std::vector<std::vector<size_t>>& indices);
137 
138  void setBoundaryConditions(std::shared_ptr<SphBoundaryConditions> sphBoundaryConditions) { m_sphBoundaryConditions = sphBoundaryConditions; }
139  std::shared_ptr<SphBoundaryConditions> getBoundaryConditions() { return m_sphBoundaryConditions; }
140 
141  void setRestDensity(const double restDensity) { m_modelParameters->m_restDensity = restDensity; }
142 
143  std::shared_ptr<TaskNode> getFindParticleNeighborsNode() const { return m_findParticleNeighborsNode; }
144  std::shared_ptr<TaskNode> getComputeDensityNode() const { return m_computeDensityNode; }
145  std::shared_ptr<TaskNode> getComputePressureNode() const { return m_computePressureAccelNode; }
146  std::shared_ptr<TaskNode> getComputeSurfaceTensionNode() const { return m_computeSurfaceTensionNode; }
147  std::shared_ptr<TaskNode> getComputeTimeStepSizeNode() const { return m_computeTimeStepSizeNode; }
148  std::shared_ptr<TaskNode> getSumAccelsNode() const { return m_sumAccelsNode; }
149  std::shared_ptr<TaskNode> getIntegrateNode() const { return m_integrateNode; }
150  std::shared_ptr<TaskNode> getComputeViscosityNode() const { return m_computeViscosityNode; }
151  std::shared_ptr<TaskNode> getUpdateVelocityNode() const { return m_updateVelocityNode; }
152  std::shared_ptr<TaskNode> getMoveParticlesNode() const { return m_moveParticlesNode; }
153 
154 protected:
158  void initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink) override;
159 
160 private:
164  void computeTimeStepSize();
165 
169  double computeCFLTimeStepSize();
170 
174  void findParticleNeighbors();
175 
179  void computeNeighborRelativePositions();
180 
185  void collectNeighborDensity();
186 
190  void computeDensity();
191 
195  void normalizeDensity();
196 
200  void computePressureAcceleration();
201 
205  void sumAccels();
206 
210  void updateVelocity(const double timestep);
211 
215  void computeViscosity();
216 
222  void computeSurfaceTension();
223 
227  void moveParticles(const double timestep);
228 
229 //void computePressureOutlet();
230 
231 protected:
232  std::shared_ptr<TaskNode> m_findParticleNeighborsNode = nullptr;
233  std::shared_ptr<TaskNode> m_computeDensityNode = nullptr;
234  std::shared_ptr<TaskNode> m_computePressureAccelNode = nullptr;
235  std::shared_ptr<TaskNode> m_computeSurfaceTensionNode = nullptr;
236  std::shared_ptr<TaskNode> m_computeTimeStepSizeNode = nullptr;
237  std::shared_ptr<TaskNode> m_sumAccelsNode = nullptr;
238  std::shared_ptr<TaskNode> m_integrateNode = nullptr;
239  std::shared_ptr<TaskNode> m_updateVelocityNode = nullptr;
240  std::shared_ptr<TaskNode> m_computeViscosityNode = nullptr;
241  std::shared_ptr<TaskNode> m_moveParticlesNode = nullptr;
242  std::shared_ptr<TaskNode> m_normalizeDensityNode = nullptr;
243  std::shared_ptr<TaskNode> m_collectNeighborDensityNode = nullptr;
244 
245 private:
246  std::shared_ptr<PointSet> m_pointSetGeometry;
247 
248  double m_dt = 0.0;
249  double m_defaultDt;
250 
251  SphSimulationKernels m_kernels;
252  std::shared_ptr<SphModelConfig> m_modelParameters;
253  std::shared_ptr<NeighborSearch> m_neighborSearcher;
254 
255  std::shared_ptr<VecDataArray<double, 3>> m_pressureAccels = nullptr;
256  std::shared_ptr<VecDataArray<double, 3>> m_surfaceTensionAccels = nullptr;
257  std::shared_ptr<VecDataArray<double, 3>> m_viscousAccels = nullptr;
258  std::shared_ptr<VecDataArray<double, 3>> m_neighborVelContr = nullptr;
259  std::shared_ptr<VecDataArray<double, 3>> m_particleShift = nullptr;
260 
261  std::shared_ptr<VecDataArray<double, 3>> m_initialVelocities = nullptr;
262  std::shared_ptr<DataArray<double>> m_initialDensities = nullptr;
263 
264  int m_timeStepCount = 0;
265 
266  std::shared_ptr<SphBoundaryConditions> m_sphBoundaryConditions = nullptr;
267 
268  std::vector<size_t> m_minIndices;
269 };
270 } // namespace imstk
void configure(const std::shared_ptr< SphModelConfig > &params)
Set simulation parameters.
Definition: imstkSphModel.h:90
double m_particleMassScale
scale particle mass to a smaller value to maintain stability
Definition: imstkSphModel.h:47
const std::shared_ptr< SphModelConfig > & getParameters() const
Get the simulation parameters.
void setTimeStep(const double timeStep) override
Set the default time step size, valid only if using a fixed time step for integration.
Compound Geometry.
void resetToInitialState() override
Reset the current state to the initial state.
double m_eta
proportion of position change due to neighbors velocity (XSPH method)
Definition: imstkSphModel.h:48
Class that holds the SPH model parameters.
Definition: imstkSphModel.h:24
void setDefaultTimeStep(const double timeStep)
Set the default time step size, valid only if using a fixed time step for integration.
Class contains SPH kernels for time integration, using different kernel for different purposes...
double getTimeStep() const override
Returns the time step size.
Base class for mathematical model of the physics governing the dynamic object.