MPS-Basic
Loading...
Searching...
No Matches
mps.cpp
Go to the documentation of this file.
1#include "mps.hpp"
2
3#include "particle.hpp"
4#include "weight.hpp"
5
6#include <queue>
7
8// This include is for checking if the pressure calculator is explicit.
9// This is needed because we need to update the pressure again when using EMPS.
11
12using std::cerr;
13using std::endl;
14
16 const Input& input,
17 Eigen::Vector3d& gravity,
18 std::unique_ptr<PressureCalculator::Interface>&& pressureCalculator,
19 std::unique_ptr<SurfaceDetector::Interface>&& surfaceDetector
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
32}
33
36 calGravity();
39
41 collision();
42
45 auto pressures = pressureCalculator->calc(particles);
46 for (auto& particle : particles) {
47 particle.pressure = pressures[particle.id];
48 }
49
53
54 // Update pressure again when using EMPS
55 if (auto explicitPressureCalculator = dynamic_cast<PressureCalculator::Explicit*>(pressureCalculator.get())) {
56 auto pressures = explicitPressureCalculator->calc(particles);
57 for (auto& particle : particles) {
58 particle.pressure = pressures[particle.id];
59 }
60 }
61
62 calCourant();
63}
64
66#pragma omp parallel for
67 for (auto& p : particles) {
68 if (p.type == ParticleType::Fluid) {
69 p.acceleration += gravity;
70 } else {
71 p.acceleration.setZero();
72 }
73 }
74}
75
76void MPS::calViscosity(const double& re) {
77 double n0 = refValuesForLaplacian.n0;
78 double lambda = refValuesForLaplacian.lambda;
79 double a = (settings.kinematicViscosity) * (2.0 * settings.dim) / (n0 * lambda);
80
81#pragma omp parallel for
82 for (auto& pi : particles) {
83 if (pi.type != ParticleType::Fluid)
84 continue;
85
86 Eigen::Vector3d viscosityTerm = Eigen::Vector3d::Zero();
87
88 for (auto& neighbor : pi.neighbors) {
89 auto& pj = particles[neighbor.id];
90
91 if (neighbor.distance < settings.re_forLaplacian) {
92 double w = weight(neighbor.distance, re);
93 viscosityTerm += (pj.velocity - pi.velocity) * w;
94 }
95 }
96
97 viscosityTerm *= a;
98 pi.acceleration += viscosityTerm;
99 }
100}
101
103#pragma omp parallel for
104 for (auto& p : particles) {
105 if (p.type == ParticleType::Fluid) {
106 p.velocity += p.acceleration * settings.dt;
107 p.position += p.velocity * settings.dt;
108 }
109 p.acceleration.setZero();
110 }
111}
112
114 for (auto& pi : particles) {
115 if (pi.type != ParticleType::Fluid)
116 continue;
117
118 for (auto& neighbor : pi.neighbors) {
119 Particle& pj = particles[neighbor.id];
120 if (pj.type == ParticleType::Fluid && pj.id >= pi.id)
121 continue;
122
123 if (neighbor.distance < settings.collisionDistance) {
124
125 double invMi = pi.inverseDensity();
126 double invMj = pj.inverseDensity();
127 double mass = 1.0 / (invMi + invMj);
128
129 Eigen::Vector3d normal = (pj.position - pi.position).normalized();
130 double relVel = (pj.velocity - pi.velocity).dot(normal);
131 double impulse = 0.0;
132 if (relVel < 0.0)
133 impulse = -(1 + settings.coefficientOfRestitution) * relVel * mass;
134 pi.velocity -= impulse * invMi * normal;
135 pj.velocity += impulse * invMj * normal;
136
137 double depth = settings.collisionDistance - neighbor.distance;
138 double positionImpulse = depth * mass;
139 pi.position -= positionImpulse * invMi * normal;
140 pj.position += positionImpulse * invMj * normal;
141
142 // cerr << "WARNING: Collision between particles " << pi.id << " and " << pj.id << " occurred."
143 // << endl;
144 }
145 }
146 }
147}
148
149void MPS::calNumberDensity(const double& re) {
150#pragma omp parallel for
151 for (auto& pi : particles) {
152 pi.numberDensity = 0.0;
153
154 if (pi.type == ParticleType::Ghost)
155 continue;
156
157 for (auto& neighbor : pi.neighbors)
158 pi.numberDensity += weight(neighbor.distance, re);
159 }
160}
161
163#pragma omp parallel for
164 for (auto& pi : particles) {
165 if (pi.type == ParticleType::Ghost || pi.type == ParticleType::DummyWall) {
166 pi.boundaryCondition = FluidState::Ignored;
167
168 } else { // Fluid particles
169 if (surfaceDetector->isFreeSurface(particles, pi)) {
170 pi.boundaryCondition = FluidState::FreeSurface;
171 } else {
172 pi.boundaryCondition = FluidState::Inner;
173 }
174 }
175 }
176}
177
178void MPS::setMinimumPressure(const double& re) {
179#pragma omp parallel for
180 for (auto& p : particles) {
181 p.minimumPressure = p.pressure;
182 }
183
184 for (auto& pi : particles) {
185 if (pi.type == ParticleType::Ghost || pi.type == ParticleType::DummyWall)
186 continue;
187
188 for (auto& neighbor : pi.neighbors) {
189 Particle& pj = particles[neighbor.id];
191 continue;
192 if (pj.id > pi.id)
193 continue;
194
195 if (neighbor.distance < re) {
196 pi.minimumPressure = std::min(pi.minimumPressure, pj.pressure);
197 pj.minimumPressure = std::min(pj.minimumPressure, pi.pressure);
198 }
199 }
200 }
201}
202
203void MPS::calPressureGradient(const double& re) {
204 double a = settings.dim / refValuesForGradient.n0;
205
206#pragma omp parallel for
207 for (auto& pi : particles) {
208 if (pi.type != ParticleType::Fluid)
209 continue;
210
211 Eigen::Vector3d grad = Eigen::Vector3d::Zero();
212 for (auto& neighbor : pi.neighbors) {
213 Particle& pj = particles[neighbor.id];
215 continue;
216
217 if (neighbor.distance < re) {
218 double w = weight(neighbor.distance, re);
219 // double dist2 = pow(neighbor.distance, 2);
220 double dist2 = (pj.position - pi.position).squaredNorm();
221 double pij = (pj.pressure - pi.minimumPressure) / dist2;
222 grad += (pj.position - pi.position) * pij * w;
223 }
224 }
225 grad *= a;
226 pi.acceleration -= grad / pi.density;
227 }
228}
229
231#pragma omp parallel for
232 for (auto&& p : particles) {
233 if (p.type == ParticleType::Fluid) {
234 p.velocity += p.acceleration * settings.dt;
235 p.position += p.acceleration * settings.dt * settings.dt;
236 }
237
238 p.acceleration.setZero();
239 }
240}
241
243 courant = 0.0;
244
245 for (auto& pi : particles) {
246 if (pi.type != ParticleType::Fluid)
247 continue;
248
249 double iCourant = (pi.velocity.norm() * settings.dt) / settings.particleDistance;
250 courant = std::max(courant, iCourant);
251 }
252
254 cerr << "ERROR: Courant number is larger than CFL condition. Courant = " << courant << endl;
255 }
256}
void setMinimumPressure(const double &re)
set minimum pressure for pressure gradient calculation
Definition mps.cpp:178
void stepForward()
Definition mps.cpp:34
void calViscosity(const double &re)
calculate viscosity term of Navier-Stokes equation
Definition mps.cpp:76
std::unique_ptr< PressureCalculator::Interface > pressureCalculator
Interface for pressure calculation.
Definition mps.hpp:35
void moveParticleUsingPressureGradient()
move particles in correction step
Definition mps.cpp:230
Settings settings
Settings for the simulation.
Definition mps.hpp:27
double courant
Maximum courant number among all particles.
Definition mps.hpp:37
void calPressureGradient(const double &re)
calculate pressure gradient term
Definition mps.cpp:203
MPS()=default
RefValues refValuesForLaplacian
Reference values for the simulation ( , )
Definition mps.hpp:30
void moveParticle()
move particles in prediction step
Definition mps.cpp:102
void setBoundaryCondition()
set boundary condition of pressure Poisson equation
Definition mps.cpp:162
RefValues refValuesForNumberDensity
Reference values for the simulation ( , )
Definition mps.hpp:29
void calCourant()
calculate Courant number
Definition mps.cpp:242
void collision()
calculate collision between particles when they are too close
Definition mps.cpp:113
Eigen::Vector3d gravity
Gravity vector for the simulation.
Definition mps.hpp:28
NeighborSearcher neighborSearcher
Neighbor searcher for neighbor search.
Definition mps.hpp:49
std::unique_ptr< SurfaceDetector::Interface > surfaceDetector
Interface for free surface detection.
Definition mps.hpp:50
void calNumberDensity(const double &re)
calculate number density of each particle
Definition mps.cpp:149
RefValues refValuesForGradient
Reference values for the simulation ( , )
Definition mps.hpp:31
void calGravity()
calculate gravity term
Definition mps.cpp:65
Particles particles
Particles in the simulation.
Definition mps.hpp:32
Domain domain
Domain of the simulation.
Definition mps.hpp:33
void setNeighbors(Particles &particles)
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
double pressure
pressure of the particle
Definition particle.hpp:58
int id
index of the particle
Definition particle.hpp:50
double minimumPressure
minimum pressure of the particle
Definition particle.hpp:64
Eigen::Vector3d velocity
velocity of the particle
Definition particle.hpp:56
ParticleType type
type of the particle
Definition particle.hpp:51
int size() const
Get the number of particles.
Definition particles.cpp:22
Class for explicit pressure calculation.
Definition explicit.hpp:14
Struct for reference values of MPS method.
Definition refvalues.hpp:8
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
@ Inner
inner fluid particle
@ FreeSurface
free surface particle
@ Ignored
Ghost or dummy.
@ Ghost
Ghost particle (outside of the domain, not used for calculation)
@ DummyWall
Dummy wall particle (pressure is not calculated)
@ Fluid
Fluid particle.
Represents the input data for MPS simulation.
Definition input.hpp:12
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:60
double collisionDistance
Distance for collision detection.
Definition settings.hpp:53
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:57
double kinematicViscosity
Kinematic viscosity.
Definition settings.hpp:28
double cflCondition
CFL condition.
Definition settings.hpp:22
double coefficientOfRestitution
Coefficient of restitution.
Definition settings.hpp:54
double re_forGradient
Effective radius for gradient.
Definition settings.hpp:58
double dt
Time step.
Definition settings.hpp:19
Domain domain
domain of the simulation
Definition settings.hpp:25
double re_forLaplacian
Effective radius for Laplacian.
Definition settings.hpp:59
double weight(double dis, double re)
Wight function for MPS method presented by Koshizuka and Oka, 1996
Definition weight.cpp:5