MPS-Basic
Loading...
Searching...
No Matches
MPS Class Reference

MPS simulation class. More...

#include <mps.hpp>

Collaboration diagram for MPS:

Public Member Functions

 MPS ()=default
 
 MPS (const Input &input, Eigen::Vector3d &gravity, std::unique_ptr< PressureCalculator::Interface > &&pressureCalculator, std::unique_ptr< SurfaceDetector::Interface > &&surfaceDetector)
 
void stepForward ()
 

Public Attributes

Settings settings
 Settings for the simulation.
 
Eigen::Vector3d gravity
 Gravity vector for the simulation.
 
RefValues refValuesForNumberDensity
 Reference values for the simulation ( \(n^0\), \(\lambda^0\))
 
RefValues refValuesForLaplacian
 Reference values for the simulation ( \(n^0\), \(\lambda^0\))
 
RefValues refValuesForGradient
 Reference values for the simulation ( \(n^0\), \(\lambda^0\))
 
Particles particles
 Particles in the simulation.
 
Domain domain {}
 Domain of the simulation.
 
std::unique_ptr< PressureCalculator::InterfacepressureCalculator
 Interface for pressure calculation.
 
double courant {}
 Maximum courant number among all particles.
 

Private Member Functions

void calGravity ()
 calculate gravity term
 
void calViscosity (const double &re)
 calculate viscosity term of Navier-Stokes equation
 
void moveParticle ()
 move particles in prediction step
 
void collision ()
 calculate collision between particles when they are too close
 
void calNumberDensity (const double &re)
 calculate number density of each particle
 
bool isParticleDistributionBiased (const Particle &pi)
 check if particle distribution is biased.
 
void setMinimumPressure (const double &re)
 set minimum pressure for pressure gradient calculation
 
void calPressureGradient (const double &re)
 calculate pressure gradient term
 
void moveParticleUsingPressureGradient ()
 move particles in correction step
 
void calCourant ()
 calculate Courant number
 

Private Attributes

NeighborSearcher neighborSearcher
 Neighbor searcher for neighbor search.
 
std::unique_ptr< SurfaceDetector::InterfacesurfaceDetector
 Interface for free surface detection.
 
Weight weight
 Weight function instance except for gradient calculation.
 
Weight weightGrad
 Weight function instance for the gradient calculation.
 

Detailed Description

MPS simulation class.

Executes the MPS simulation. This class does not handle the simulation process itself, but only the calculation of the MPS method.

Definition at line 26 of file mps.hpp.

Constructor & Destructor Documentation

◆ MPS() [1/2]

MPS::MPS ( )
default

◆ MPS() [2/2]

MPS::MPS ( const Input & input,
Eigen::Vector3d & gravity,
std::unique_ptr< PressureCalculator::Interface > && pressureCalculator,
std::unique_ptr< SurfaceDetector::Interface > && surfaceDetector )

Definition at line 15 of file mps.cpp.

20 {
21 this->settings = input.settings;
22 this->domain = input.settings.domain;
23 this->particles = input.particles;
24 this->gravity = gravity;
25 this->pressureCalculator = std::move(pressureCalculator);
26 this->surfaceDetector = std::move(surfaceDetector);
28
34 );
40 );
46 );
47
48 this->weight =
50 this->weightGrad = Weight(
52 );
53}
std::unique_ptr< PressureCalculator::Interface > pressureCalculator
Interface for pressure calculation.
Definition mps.hpp:36
Settings settings
Settings for the simulation.
Definition mps.hpp:28
Weight weightGrad
Weight function instance for the gradient calculation.
Definition mps.hpp:53
RefValues refValuesForLaplacian
Reference values for the simulation ( , )
Definition mps.hpp:31
RefValues refValuesForNumberDensity
Reference values for the simulation ( , )
Definition mps.hpp:30
Eigen::Vector3d gravity
Gravity vector for the simulation.
Definition mps.hpp:29
NeighborSearcher neighborSearcher
Neighbor searcher for neighbor search.
Definition mps.hpp:50
std::unique_ptr< SurfaceDetector::Interface > surfaceDetector
Interface for free surface detection.
Definition mps.hpp:51
RefValues refValuesForGradient
Reference values for the simulation ( , )
Definition mps.hpp:32
Weight weight
Weight function instance except for gradient calculation.
Definition mps.hpp:52
Particles particles
Particles in the simulation.
Definition mps.hpp:33
Domain domain
Domain of the simulation.
Definition mps.hpp:34
int size() const
Get the number of particles.
Definition particles.cpp:22
Struct for reference values of MPS method.
Definition refvalues.hpp:9
Provides a weight function.
Definition weight.hpp:15
Particles particles
Initial particles arrangement in the simulation.
Definition input.hpp:14
Settings settings
Settings for the simulation.
Definition input.hpp:13
double reMax
Maximum of effective radius.
Definition settings.hpp:59
double particleDistance
Initial distance between particles.
Definition settings.hpp:18
int dim
Dimension of the simulation.
Definition settings.hpp:17
double re_forNumberDensity
Effective radius for number density.
Definition settings.hpp:56
std::string pressureCalculationMethod
Method for pressure calculation.
Definition settings.hpp:44
double re_forGradient
Effective radius for gradient.
Definition settings.hpp:57
Domain domain
domain of the simulation
Definition settings.hpp:24
double re_forLaplacian
Effective radius for Laplacian.
Definition settings.hpp:58
Here is the call graph for this function:

Member Function Documentation

◆ stepForward()

void MPS::stepForward ( )

Definition at line 55 of file mps.cpp.

55 {
57 calGravity();
60
62 collision();
63
66 auto pressures = pressureCalculator->calc(particles);
67 for (auto& particle : particles) {
68 particle.pressure = pressures[particle.id];
69 }
70
71 if (settings.pressureCalculationMethod == "Implicit")
75
76 // Update pressure again when using EMPS
77 if (auto explicitPressureCalculator = dynamic_cast<PressureCalculator::Explicit*>(pressureCalculator.get())) {
78 auto pressures = explicitPressureCalculator->calc(particles);
79 for (auto& particle : particles) {
80 particle.pressure = pressures[particle.id];
81 }
82 }
83
84 calCourant();
85}
void setMinimumPressure(const double &re)
set minimum pressure for pressure gradient calculation
Definition mps.cpp:184
void calViscosity(const double &re)
calculate viscosity term of Navier-Stokes equation
Definition mps.cpp:98
void moveParticleUsingPressureGradient()
move particles in correction step
Definition mps.cpp:238
void calPressureGradient(const double &re)
calculate pressure gradient term
Definition mps.cpp:209
void moveParticle()
move particles in prediction step
Definition mps.cpp:124
void calCourant()
calculate Courant number
Definition mps.cpp:250
void collision()
calculate collision between particles when they are too close
Definition mps.cpp:135
void calNumberDensity(const double &re)
calculate number density of each particle
Definition mps.cpp:171
void calGravity()
calculate gravity term
Definition mps.cpp:87
void setNeighbors(Particles &particles)
Class for explicit pressure calculation.
Definition explicit.hpp:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calGravity()

void MPS::calGravity ( )
private

calculate gravity term

Definition at line 87 of file mps.cpp.

87 {
88#pragma omp parallel for
89 for (auto& p : particles) {
90 if (p.type == ParticleType::Fluid) {
91 p.acceleration += gravity;
92 } else {
93 p.acceleration.setZero();
94 }
95 }
96}
@ Fluid
Fluid particle.
Here is the caller graph for this function:

◆ calViscosity()

void MPS::calViscosity ( const double & re)
private

calculate viscosity term of Navier-Stokes equation

Parameters
reeffective radius \(r_e\)

The viscosity term of the Navier-Stokes equation is calculated as follows:

\[ \nu\langle \nabla^2\mathbf{u}\rangle_i = \nu\frac{2 d}{n^0\lambda^0}\sum_{j\neq i} (\mathbf{u}_j - \mathbf{u}_i) w_{ij} \]

Definition at line 98 of file mps.cpp.

98 {
99 double n0 = refValuesForLaplacian.n0;
100 double lambda = refValuesForLaplacian.lambda;
101 double a = (settings.kinematicViscosity) * (2.0 * settings.dim) / (n0 * lambda);
102
103#pragma omp parallel for
104 for (auto& pi : particles) {
105 if (pi.type != ParticleType::Fluid)
106 continue;
107
108 Eigen::Vector3d viscosityTerm = Eigen::Vector3d::Zero();
109
110 for (auto& neighbor : pi.neighbors) {
111 auto& pj = particles[neighbor.id];
112
113 if (neighbor.distance < re) {
114 double w = weight.weightFn(neighbor.distance, re);
115 viscosityTerm += (pj.velocity - pi.velocity) * w;
116 }
117 }
118
119 viscosityTerm *= a;
120 pi.acceleration += viscosityTerm;
121 }
122}
double n0
reference value of number density for source term of pressure Poisson equation
Definition refvalues.hpp:11
double lambda
coefficient for laplacian
Definition refvalues.hpp:12
double weightFn(double dis, double re)
Weight function for MPS method.
Definition weight.cpp:10
double kinematicViscosity
Kinematic viscosity.
Definition settings.hpp:27
Here is the call graph for this function:
Here is the caller graph for this function:

◆ moveParticle()

void MPS::moveParticle ( )
private

move particles in prediction step

The position and velocity of each particle are updated as

\[ \mathbf{u}_i^* = \mathbf{u}_i^k + (\nu\langle \nabla^2\mathbf{u}\rangle^k_i+\mathbf{g})\Delta t. \]

Definition at line 124 of file mps.cpp.

124 {
125#pragma omp parallel for
126 for (auto& p : particles) {
127 if (p.type == ParticleType::Fluid) {
128 p.velocity += p.acceleration * settings.dt;
129 p.position += p.velocity * settings.dt;
130 }
131 p.acceleration.setZero();
132 }
133}
double dt
Time step.
Definition settings.hpp:19
Here is the caller graph for this function:

◆ collision()

void MPS::collision ( )
private

calculate collision between particles when they are too close

Definition at line 135 of file mps.cpp.

135 {
136 for (auto& pi : particles) {
137 if (pi.type != ParticleType::Fluid)
138 continue;
139
140 for (auto& neighbor : pi.neighbors) {
141 Particle& pj = particles[neighbor.id];
142 if (pj.type == ParticleType::Fluid && pj.id >= pi.id)
143 continue;
144
145 if (neighbor.distance < settings.collisionDistance) {
146
147 double invMi = pi.inverseDensity();
148 double invMj = pj.inverseDensity();
149 double mass = 1.0 / (invMi + invMj);
150
151 Eigen::Vector3d normal = (pj.position - pi.position).normalized();
152 double relVel = (pj.velocity - pi.velocity).dot(normal);
153 double impulse = 0.0;
154 if (relVel < 0.0)
155 impulse = -(1 + settings.coefficientOfRestitution) * relVel * mass;
156 pi.velocity -= impulse * invMi * normal;
157 pj.velocity += impulse * invMj * normal;
158
159 double depth = settings.collisionDistance - neighbor.distance;
160 double positionImpulse = depth * mass;
161 pi.position -= positionImpulse * invMi * normal;
162 pj.position += positionImpulse * invMj * normal;
163
164 // cerr << "WARNING: Collision between particles " << pi.id << " and " << pj.id << " occurred."
165 // << endl;
166 }
167 }
168 }
169}
Class for particle in MPS method.
Definition particle.hpp:47
double inverseDensity() const
calculate inverse of density for collision
Definition particle.cpp:12
Eigen::Vector3d position
position of the particle
Definition particle.hpp:55
int id
index of the particle
Definition particle.hpp:50
Eigen::Vector3d velocity
velocity of the particle
Definition particle.hpp:56
ParticleType type
type of the particle
Definition particle.hpp:51
double collisionDistance
Distance for collision detection.
Definition settings.hpp:52
double coefficientOfRestitution
Coefficient of restitution.
Definition settings.hpp:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calNumberDensity()

void MPS::calNumberDensity ( const double & re)
private

calculate number density of each particle

Parameters
reeffective radius \(r_e\)

Definition at line 171 of file mps.cpp.

171 {
172#pragma omp parallel for
173 for (auto& pi : particles) {
174 pi.numberDensity = 0.0;
175
176 if (pi.type == ParticleType::Ghost)
177 continue;
178
179 for (auto& neighbor : pi.neighbors)
180 pi.numberDensity += weight.weightFn(neighbor.distance, re);
181 }
182}
@ Ghost
Ghost particle (outside of the domain, not used for calculation)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isParticleDistributionBiased()

bool MPS::isParticleDistributionBiased ( const Particle & pi)
private

check if particle distribution is biased.

Particle number density can be low even in the fluid region, making the free surface detection based on particle number density vulnerable. Even when a specific particle's the particle number density is lower than criteria, it can be considered as inner particle if the particle distribution around the particle is not biased. In this way we can avoid the free surface detection error. This is based on Khayyer et al. (https://doi.org/10.1016/j.apor.2009.06.003)

Parameters
piParticle to check
Returns
true particle distribution is biased = free surface
false particle distribution is not biased = not free surface

◆ setMinimumPressure()

void MPS::setMinimumPressure ( const double & re)
private

set minimum pressure for pressure gradient calculation

Parameters
reeffective radius \(r_e\) This function is needed only in semi-implicit method.

Definition at line 184 of file mps.cpp.

184 {
185#pragma omp parallel for
186 for (auto& p : particles) {
187 p.minimumPressure = p.pressure;
188 }
189
190 for (auto& pi : particles) {
191 if (pi.type == ParticleType::Ghost || pi.type == ParticleType::DummyWall)
192 continue;
193
194 for (auto& neighbor : pi.neighbors) {
195 Particle& pj = particles[neighbor.id];
197 continue;
198 if (pj.id > pi.id)
199 continue;
200
201 if (neighbor.distance < re) {
202 pi.minimumPressure = std::min(pi.minimumPressure, pj.pressure);
203 pj.minimumPressure = std::min(pj.minimumPressure, pi.pressure);
204 }
205 }
206 }
207}
double pressure
pressure of the particle
Definition particle.hpp:58
double minimumPressure
minimum pressure of the particle
Definition particle.hpp:64
@ DummyWall
Dummy wall particle (pressure is not calculated)
Here is the caller graph for this function:

◆ calPressureGradient()

void MPS::calPressureGradient ( const double & re)
private

calculate pressure gradient term

Parameters
re

The pressure gradient term of the Navier-Stokes equation is calculated as

\[ -\frac{1}{\rho^0}\langle\nabla P\rangle_i = -\frac{1}{\rho^0}\frac{d}{n^0}\sum_{j\neq i} \frac{P_j-P'_i}{\|\mathbf{r}_{ij}\|^2}\mathbf{r}_{ij} w_{ij} \]

where \(P'_i\) is the minimum pressure of the particle \(i\).

Definition at line 209 of file mps.cpp.

209 {
210 double a = settings.dim / refValuesForGradient.n0;
211
212#pragma omp parallel for
213 for (auto& pi : particles) {
214 if (pi.type != ParticleType::Fluid)
215 continue;
216
217 Eigen::Vector3d grad = Eigen::Vector3d::Zero();
218 for (auto& neighbor : pi.neighbors) {
219 Particle& pj = particles[neighbor.id];
221 continue;
222
223 if (neighbor.distance < re) {
224 double w = weightGrad.weightFn(neighbor.distance, re);
225 // double dist2 = pow(neighbor.distance, 2);
226 double dist2 = (pj.position - pi.position).squaredNorm();
227 double pij = (settings.pressureCalculationMethod == "Implicit")
228 ? (pj.pressure - pi.minimumPressure) / dist2
229 : (pj.pressure + pi.pressure) / dist2;
230 grad += (pj.position - pi.position) * pij * w;
231 }
232 }
233 grad *= a;
234 pi.acceleration -= grad / pi.density;
235 }
236}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ moveParticleUsingPressureGradient()

void MPS::moveParticleUsingPressureGradient ( )
private

move particles in correction step

The position and velocity of each particle are updated as

\[ \mathbf{u}_i^{k+1} = \mathbf{u}_i^* - \frac{1}{\rho^0} \langle\nabla P^{k+1} \rangle_i \Delta t. \]

Definition at line 238 of file mps.cpp.

238 {
239#pragma omp parallel for
240 for (auto&& p : particles) {
241 if (p.type == ParticleType::Fluid) {
242 p.velocity += p.acceleration * settings.dt;
243 p.position += p.acceleration * settings.dt * settings.dt;
244 }
245
246 p.acceleration.setZero();
247 }
248}
Here is the caller graph for this function:

◆ calCourant()

void MPS::calCourant ( )
private

calculate Courant number

Definition at line 250 of file mps.cpp.

250 {
251 courant = 0.0;
252
253 for (auto& pi : particles) {
254 if (pi.type != ParticleType::Fluid)
255 continue;
256
257 double iCourant = (pi.velocity.norm() * settings.dt) / settings.particleDistance;
258 courant = std::max(courant, iCourant);
259 }
260
262 cerr << "ERROR: Courant number is larger than CFL condition. Courant = " << courant << endl;
263 }
264}
double courant
Maximum courant number among all particles.
Definition mps.hpp:38
double cflCondition
CFL condition.
Definition settings.hpp:22
Here is the caller graph for this function:

Member Data Documentation

◆ settings

Settings MPS::settings

Settings for the simulation.

Definition at line 28 of file mps.hpp.

◆ gravity

Eigen::Vector3d MPS::gravity

Gravity vector for the simulation.

Definition at line 29 of file mps.hpp.

◆ refValuesForNumberDensity

RefValues MPS::refValuesForNumberDensity

Reference values for the simulation ( \(n^0\), \(\lambda^0\))

Definition at line 30 of file mps.hpp.

◆ refValuesForLaplacian

RefValues MPS::refValuesForLaplacian

Reference values for the simulation ( \(n^0\), \(\lambda^0\))

Definition at line 31 of file mps.hpp.

◆ refValuesForGradient

RefValues MPS::refValuesForGradient

Reference values for the simulation ( \(n^0\), \(\lambda^0\))

Definition at line 32 of file mps.hpp.

◆ particles

Particles MPS::particles

Particles in the simulation.

Definition at line 33 of file mps.hpp.

◆ domain

Domain MPS::domain {}

Domain of the simulation.

Definition at line 34 of file mps.hpp.

34{};

◆ pressureCalculator

std::unique_ptr<PressureCalculator::Interface> MPS::pressureCalculator

Interface for pressure calculation.

Definition at line 36 of file mps.hpp.

◆ courant

double MPS::courant {}

Maximum courant number among all particles.

Definition at line 38 of file mps.hpp.

38{};

◆ neighborSearcher

NeighborSearcher MPS::neighborSearcher
private

Neighbor searcher for neighbor search.

Definition at line 50 of file mps.hpp.

◆ surfaceDetector

std::unique_ptr<SurfaceDetector::Interface> MPS::surfaceDetector
private

Interface for free surface detection.

Definition at line 51 of file mps.hpp.

◆ weight

Weight MPS::weight
private

Weight function instance except for gradient calculation.

Definition at line 52 of file mps.hpp.

◆ weightGrad

Weight MPS::weightGrad
private

Weight function instance for the gradient calculation.

Definition at line 53 of file mps.hpp.


The documentation for this class was generated from the following files: