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, std::unique_ptr< PressureCalculator::Interface > &&pressureCalculator, std::unique_ptr< SurfaceDetector::Interface > &&surfaceDetector)
 
void stepForward ()
 

Public Attributes

Settings settings
 Settings 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
 
void setBoundaryCondition ()
 set boundary condition of pressure Poisson equation
 
bool isFreeSurface (const Particle &pi)
 
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.
 

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 25 of file mps.hpp.

Constructor & Destructor Documentation

◆ MPS() [1/2]

MPS::MPS ( )
default

◆ MPS() [2/2]

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

Definition at line 15 of file mps.cpp.

19 {
20 this->settings = input.settings;
21 this->domain = input.settings.domain;
22 this->particles = input.particles;
23 this->pressureCalculator = std::move(pressureCalculator);
24 this->surfaceDetector = std::move(surfaceDetector);
26
30}
std::unique_ptr< PressureCalculator::Interface > pressureCalculator
Interface for pressure calculation.
Definition mps.hpp:34
Settings settings
Settings for the simulation.
Definition mps.hpp:27
RefValues refValuesForLaplacian
Reference values for the simulation ( , )
Definition mps.hpp:29
RefValues refValuesForNumberDensity
Reference values for the simulation ( , )
Definition mps.hpp:28
NeighborSearcher neighborSearcher
Neighbor searcher for neighbor search.
Definition mps.hpp:47
std::unique_ptr< SurfaceDetector::Interface > surfaceDetector
Interface for free surface detection.
Definition mps.hpp:48
RefValues refValuesForGradient
Reference values for the simulation ( , )
Definition mps.hpp:30
Particles particles
Particles in the simulation.
Definition mps.hpp:31
Domain domain
Domain of the simulation.
Definition mps.hpp:32
int size() const
Get the number of particles.
Definition particles.cpp:21
Struct for reference values of MPS method.
Definition refvalues.hpp:8
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:57
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:54
double re_forGradient
Effective radius for gradient.
Definition settings.hpp:55
Domain domain
domain of the simulation
Definition settings.hpp:25
double re_forLaplacian
Effective radius for Laplacian.
Definition settings.hpp:56
Here is the call graph for this function:

Member Function Documentation

◆ stepForward()

void MPS::stepForward ( )

Definition at line 32 of file mps.cpp.

32 {
34 calGravity();
37
39 collision();
40
43 auto pressures = pressureCalculator->calc(particles);
44 for (auto& particle : particles) {
45 particle.pressure = pressures[particle.id];
46 }
47
51
52 // Update pressure again when using EMPS
53 if (auto explicitPressureCalculator = dynamic_cast<PressureCalculator::Explicit*>(pressureCalculator.get())) {
54 auto pressures = explicitPressureCalculator->calc(particles);
55 for (auto& particle : particles) {
56 particle.pressure = pressures[particle.id];
57 }
58 }
59
60 calCourant();
61}
void setMinimumPressure(const double &re)
set minimum pressure for pressure gradient calculation
Definition mps.cpp:177
void calViscosity(const double &re)
calculate viscosity term of Navier-Stokes equation
Definition mps.cpp:75
void moveParticleUsingPressureGradient()
move particles in correction step
Definition mps.cpp:229
void calPressureGradient(const double &re)
calculate pressure gradient term
Definition mps.cpp:202
void moveParticle()
move particles in prediction step
Definition mps.cpp:101
void calCourant()
calculate Courant number
Definition mps.cpp:241
void collision()
calculate collision between particles when they are too close
Definition mps.cpp:112
void calNumberDensity(const double &re)
calculate number density of each particle
Definition mps.cpp:148
void calGravity()
calculate gravity term
Definition mps.cpp:63
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 63 of file mps.cpp.

63 {
64#pragma omp parallel for
65 for (auto& p : particles) {
66 if (p.type == ParticleType::Fluid) {
67 p.acceleration += settings.gravity;
68
69 } else {
70 p.acceleration.setZero();
71 }
72 }
73}
@ Fluid
Fluid particle.
Eigen::Vector3d gravity
Gravity.
Definition settings.hpp:32
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 75 of file mps.cpp.

75 {
76 double n0 = refValuesForLaplacian.n0;
77 double lambda = refValuesForLaplacian.lambda;
78 double a = (settings.kinematicViscosity) * (2.0 * settings.dim) / (n0 * lambda);
79
80#pragma omp parallel for
81 for (auto& pi : particles) {
82 if (pi.type != ParticleType::Fluid)
83 continue;
84
85 Eigen::Vector3d viscosityTerm = Eigen::Vector3d::Zero();
86
87 for (auto& neighbor : pi.neighbors) {
88 auto& pj = particles[neighbor.id];
89
90 if (neighbor.distance < settings.re_forLaplacian) {
91 double w = weight(neighbor.distance, re);
92 viscosityTerm += (pj.velocity - pi.velocity) * w;
93 }
94 }
95
96 viscosityTerm *= a;
97 pi.acceleration += viscosityTerm;
98 }
99}
double n0
reference value of number density for source term of pressure Poisson equation
Definition refvalues.hpp:10
double lambda
coefficient for laplacian
Definition refvalues.hpp:11
double kinematicViscosity
Kinematic viscosity.
Definition settings.hpp:28
double weight(double dis, double re)
Wight function for MPS method presented by Koshizuka and Oka, 1996
Definition weight.cpp:5
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 101 of file mps.cpp.

101 {
102#pragma omp parallel for
103 for (auto& p : particles) {
104 if (p.type == ParticleType::Fluid) {
105 p.velocity += p.acceleration * settings.dt;
106 p.position += p.velocity * settings.dt;
107 }
108 p.acceleration.setZero();
109 }
110}
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 112 of file mps.cpp.

112 {
113 for (auto& pi : particles) {
114 if (pi.type != ParticleType::Fluid)
115 continue;
116
117 for (auto& neighbor : pi.neighbors) {
118 Particle& pj = particles[neighbor.id];
119 if (pj.type == ParticleType::Fluid && pj.id >= pi.id)
120 continue;
121
122 if (neighbor.distance < settings.collisionDistance) {
123
124 double invMi = pi.inverseDensity();
125 double invMj = pj.inverseDensity();
126 double mass = 1.0 / (invMi + invMj);
127
128 Eigen::Vector3d normal = (pj.position - pi.position).normalized();
129 double relVel = (pj.velocity - pi.velocity).dot(normal);
130 double impulse = 0.0;
131 if (relVel < 0.0)
132 impulse = -(1 + settings.coefficientOfRestitution) * relVel * mass;
133 pi.velocity -= impulse * invMi * normal;
134 pj.velocity += impulse * invMj * normal;
135
136 double depth = settings.collisionDistance - neighbor.distance;
137 double positionImpulse = depth * mass;
138 pi.position -= positionImpulse * invMi * normal;
139 pj.position += positionImpulse * invMj * normal;
140
141 // cerr << "WARNING: Collision between particles " << pi.id << " and " << pj.id << " occurred."
142 // << endl;
143 }
144 }
145 }
146}
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:50
double coefficientOfRestitution
Coefficient of restitution.
Definition settings.hpp:51
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 148 of file mps.cpp.

148 {
149#pragma omp parallel for
150 for (auto& pi : particles) {
151 pi.numberDensity = 0.0;
152
153 if (pi.type == ParticleType::Ghost)
154 continue;
155
156 for (auto& neighbor : pi.neighbors)
157 pi.numberDensity += weight(neighbor.distance, re);
158 }
159}
@ 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:

◆ setBoundaryCondition()

void MPS::setBoundaryCondition ( )
private

set boundary condition of pressure Poisson equation

Definition at line 161 of file mps.cpp.

161 {
162#pragma omp parallel for
163 for (auto& pi : particles) {
164 if (pi.type == ParticleType::Ghost || pi.type == ParticleType::DummyWall) {
165 pi.boundaryCondition = FluidState::Ignored;
166
167 } else { // Fluid particles
168 if (surfaceDetector->isFreeSurface(particles, pi)) {
169 pi.boundaryCondition = FluidState::FreeSurface;
170 } else {
171 pi.boundaryCondition = FluidState::Inner;
172 }
173 }
174 }
175}
@ Inner
inner fluid particle
@ FreeSurface
free surface particle
@ Ignored
Ghost or dummy.
@ DummyWall
Dummy wall particle (pressure is not calculated)

◆ isFreeSurface()

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

◆ 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\)

Definition at line 177 of file mps.cpp.

177 {
178#pragma omp parallel for
179 for (auto& p : particles) {
180 p.minimumPressure = p.pressure;
181 }
182
183 for (auto& pi : particles) {
184 if (pi.type == ParticleType::Ghost || pi.type == ParticleType::DummyWall)
185 continue;
186
187 for (auto& neighbor : pi.neighbors) {
188 Particle& pj = particles[neighbor.id];
190 continue;
191 if (pj.id > pi.id)
192 continue;
193
194 if (neighbor.distance < re) {
195 pi.minimumPressure = std::min(pi.minimumPressure, pj.pressure);
196 pj.minimumPressure = std::min(pj.minimumPressure, pi.pressure);
197 }
198 }
199 }
200}
double pressure
pressure of the particle
Definition particle.hpp:58
double minimumPressure
minimum pressure of the particle
Definition particle.hpp:64
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 202 of file mps.cpp.

202 {
203 double a = settings.dim / refValuesForGradient.n0;
204
205#pragma omp parallel for
206 for (auto& pi : particles) {
207 if (pi.type != ParticleType::Fluid)
208 continue;
209
210 Eigen::Vector3d grad = Eigen::Vector3d::Zero();
211 for (auto& neighbor : pi.neighbors) {
212 Particle& pj = particles[neighbor.id];
214 continue;
215
216 if (neighbor.distance < re) {
217 double w = weight(neighbor.distance, re);
218 // double dist2 = pow(neighbor.distance, 2);
219 double dist2 = (pj.position - pi.position).squaredNorm();
220 double pij = (pj.pressure - pi.minimumPressure) / dist2;
221 grad += (pj.position - pi.position) * pij * w;
222 }
223 }
224 grad *= a;
225 pi.acceleration -= grad / pi.density;
226 }
227}
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 229 of file mps.cpp.

229 {
230#pragma omp parallel for
231 for (auto&& p : particles) {
232 if (p.type == ParticleType::Fluid) {
233 p.velocity += p.acceleration * settings.dt;
234 p.position += p.acceleration * settings.dt * settings.dt;
235 }
236
237 p.acceleration.setZero();
238 }
239}
Here is the caller graph for this function:

◆ calCourant()

void MPS::calCourant ( )
private

calculate Courant number

Definition at line 241 of file mps.cpp.

241 {
242 courant = 0.0;
243
244 for (auto& pi : particles) {
245 if (pi.type != ParticleType::Fluid)
246 continue;
247
248 double iCourant = (pi.velocity.norm() * settings.dt) / settings.particleDistance;
249 courant = std::max(courant, iCourant);
250 }
251
253 cerr << "ERROR: Courant number is larger than CFL condition. Courant = " << courant << endl;
254 }
255}
double courant
Maximum courant number among all particles.
Definition mps.hpp:36
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 27 of file mps.hpp.

◆ refValuesForNumberDensity

RefValues MPS::refValuesForNumberDensity

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

Definition at line 28 of file mps.hpp.

◆ refValuesForLaplacian

RefValues MPS::refValuesForLaplacian

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

Definition at line 29 of file mps.hpp.

◆ refValuesForGradient

RefValues MPS::refValuesForGradient

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

Definition at line 30 of file mps.hpp.

◆ particles

Particles MPS::particles

Particles in the simulation.

Definition at line 31 of file mps.hpp.

◆ domain

Domain MPS::domain {}

Domain of the simulation.

Definition at line 32 of file mps.hpp.

32{};

◆ pressureCalculator

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

Interface for pressure calculation.

Definition at line 34 of file mps.hpp.

◆ courant

double MPS::courant {}

Maximum courant number among all particles.

Definition at line 36 of file mps.hpp.

36{};

◆ neighborSearcher

NeighborSearcher MPS::neighborSearcher
private

Neighbor searcher for neighbor search.

Definition at line 47 of file mps.hpp.

◆ surfaceDetector

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

Interface for free surface detection.

Definition at line 48 of file mps.hpp.


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