Skip to content

Commit 8d937b9

Browse files
author
yzeng
committed
add the level set function support for the ellipsoid geometry
1 parent b0e245e commit 8d937b9

File tree

5 files changed

+271
-35
lines changed

5 files changed

+271
-35
lines changed

Source/DiffusedIB.H

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ struct kernel{
6464

6565
RealVect varphi{0.0,0.0,0.0};
6666
Real radius{0.0};
67+
Real radius2{0.0};
68+
Real radius3{0.0};
69+
int geometry_type{1}; // 1 = sphere, 2 = ellipsoid, 3 = cylinder
6770
Real rho{0.0};
6871
int ml{0};
6972
Real dv{0.0};
@@ -133,6 +136,9 @@ public:
133136
const Vector<int>& RLY,
134137
const Vector<int>& RLZ,
135138
const Vector<Real>& radius,
139+
const Vector<Real>& radius2,
140+
const Vector<Real>& radius3,
141+
const Vector<int>& geometry_type,
136142
Real h,
137143
Real gravity,
138144
int verbose = 0);

Source/DiffusedIB.cpp

Lines changed: 129 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ namespace ParticleProperties{
3434
Vector<Real> Vx{}, Vy{}, Vz{};
3535
Vector<Real> Ox{}, Oy{}, Oz{};
3636
Vector<Real> _radius;
37+
Vector<Real> _radius2;
38+
Vector<Real> _radius3;
39+
Vector<int> _geometry_type;
3740
Real rd{0.0};
3841
Vector<int> TLX{}, TLY{},TLZ{},RLX{},RLY{},RLZ{};
3942
int euler_finest_level{0};
@@ -107,7 +110,8 @@ void calculate_phi_nodal(MultiFab& phi_nodal, kernel& current_kernel)
107110
amrex::Real Xp = current_kernel.location[0];
108111
amrex::Real Yp = current_kernel.location[1];
109112
amrex::Real Zp = current_kernel.location[2];
110-
amrex::Real Rp = current_kernel.radius;
113+
amrex::Real a = current_kernel.radius;
114+
int geometry_type = current_kernel.geometry_type;
111115

112116
// Only set the valid cells of phi_nodal
113117
for (MFIter mfi(phi_nodal,TilingIfNotGPU()); mfi.isValid(); ++mfi)
@@ -116,19 +120,69 @@ void calculate_phi_nodal(MultiFab& phi_nodal, kernel& current_kernel)
116120
auto const& pnfab = phi_nodal.array(mfi);
117121
auto dx = ParticleProperties::dx;
118122
auto plo = ParticleProperties::plo;
119-
amrex::ParallelFor(bx, [=]
120-
AMREX_GPU_DEVICE(int i, int j, int k) noexcept
121-
{
122-
Real Xn = i * dx[0] + plo[0];
123-
Real Yn = j * dx[1] + plo[1];
124-
Real Zn = k * dx[2] + plo[2];
123+
124+
if (geometry_type == 1) {
125+
// Sphere geometry
126+
amrex::ParallelFor(bx, [=]
127+
AMREX_GPU_DEVICE(int i, int j, int k) noexcept
128+
{
129+
Real Xn = i * dx[0] + plo[0];
130+
Real Yn = j * dx[1] + plo[1];
131+
Real Zn = k * dx[2] + plo[2];
125132

126-
pnfab(i,j,k) = std::sqrt( (Xn - Xp)*(Xn - Xp)
127-
+ (Yn - Yp)*(Yn - Yp) + (Zn - Zp)*(Zn - Zp)) - Rp;
128-
pnfab(i,j,k) = pnfab(i,j,k) / Rp;
133+
pnfab(i,j,k) = std::sqrt( (Xn - Xp)*(Xn - Xp)
134+
+ (Yn - Yp)*(Yn - Yp) + (Zn - Zp)*(Zn - Zp)) - a;
135+
pnfab(i,j,k) = pnfab(i,j,k) / a;
129136

130-
}
131-
);
137+
}
138+
);
139+
} else if (geometry_type == 2) {
140+
// Ellipsoid geometry
141+
Real b = current_kernel.radius2; // semi-axis b
142+
Real c = current_kernel.radius3; // semi-axis c
143+
amrex::ParallelFor(bx, [=]
144+
AMREX_GPU_DEVICE(int i, int j, int k) noexcept
145+
{
146+
Real Xn = i * dx[0] + plo[0];
147+
Real Yn = j * dx[1] + plo[1];
148+
Real Zn = k * dx[2] + plo[2];
149+
150+
// Relative coordinates to ellipsoid center
151+
Real xp = Xn - Xp;
152+
Real yp = Yn - Yp;
153+
Real zp = Zn - Zp;
154+
155+
// Compute ellipsoid level set function using the formula:
156+
// d ≈ (x'^2/a^2 + y'^2/b^2 + z'^2/c^2 - 1) / (2 * sqrt(x'^4/a^4 + y'^4/b^4 + z'^4/c^4))
157+
Real xp2 = xp * xp;
158+
Real yp2 = yp * yp;
159+
Real zp2 = zp * zp;
160+
161+
Real a2 = a * a;
162+
Real b2 = b * b;
163+
Real c2 = c * c;
164+
165+
Real numerator = (xp2 / a2 + yp2 / b2 + zp2 / c2) - 1.0;
166+
167+
Real xp4 = xp2 * xp2;
168+
Real yp4 = yp2 * yp2;
169+
Real zp4 = zp2 * zp2;
170+
171+
Real a4 = a2 * a2;
172+
Real b4 = b2 * b2;
173+
Real c4 = c2 * c2;
174+
175+
Real denominator = 2.0 * std::sqrt(xp4 / a4 + yp4 / b4 + zp4 / c4);
176+
177+
// Do not normalize here!
178+
pnfab(i,j,k) = numerator / (denominator + 1.e-12);
179+
180+
}
181+
);
182+
} else if (geometry_type > 2) {
183+
amrex::Print() << "Particle (" << current_kernel.id << ") has unsupported geometry_type: " << geometry_type << "\n";
184+
amrex::Abort("Unsupported geometry type. Only geometry_type = 1 (sphere) and 2 (ellipsoid) are supported.");
185+
}
132186
}
133187
}
134188

@@ -195,9 +249,36 @@ void CalculateSumT_cir (RealVect& sum,
195249
}
196250

197251
[[nodiscard]] AMREX_FORCE_INLINE
198-
Real cal_momentum(Real rho, Real radius)
252+
Real cal_momentum(Real rho, Real radius, int geometry_type = 1, int idir = 0, Real radius2 = 0.0, Real radius3 = 0.0)
199253
{
200-
return 8.0 * Math::pi<Real>() * rho * Math::powi<5>(radius) / 15.0;
254+
if (geometry_type == 1) {
255+
// Sphere: I = (2/5) * m * r² = (8/15) * π * ρ * r⁵
256+
return 8.0 * Math::pi<Real>() * rho * Math::powi<5>(radius) / 15.0;
257+
} else if (geometry_type == 2) {
258+
// Ellipsoid: I = (1/5) * m * (sum of squares of perpendicular semi-axes)
259+
// m = (4/3) * π * a * b * c * ρ
260+
Real a = radius;
261+
Real b = (radius2 > 0.0) ? radius2 : radius;
262+
Real c = (radius3 > 0.0) ? radius3 : radius;
263+
Real m = 4.0 * Math::pi<Real>() * rho * a * b * c / 3.0;
264+
265+
// Moment of inertia depends on rotation axis
266+
Real I;
267+
if (idir == 0) {
268+
// Rotation around x-axis (a-axis): I_x = (1/5) * m * (b² + c²)
269+
I = m * (b * b + c * c) / 5.0;
270+
} else if (idir == 1) {
271+
// Rotation around y-axis (b-axis): I_y = (1/5) * m * (a² + c²)
272+
I = m * (a * a + c * c) / 5.0;
273+
} else {
274+
// Rotation around z-axis (c-axis): I_z = (1/5) * m * (a² + b²)
275+
I = m * (a * a + b * b) / 5.0;
276+
}
277+
return I;
278+
} else {
279+
// Default to sphere for unsupported geometry types
280+
return 8.0 * Math::pi<Real>() * rho * Math::powi<5>(radius) / 15.0;
281+
}
201282
}
202283

203284
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
@@ -298,6 +379,9 @@ void mParticle::InitParticles(const Vector<Real>& x,
298379
const Vector<int>& RLYt,
299380
const Vector<int>& RLZt,
300381
const Vector<Real>& radius,
382+
const Vector<Real>& radius2,
383+
const Vector<Real>& radius3,
384+
const Vector<int>& geometry_type,
301385
Real h,
302386
Real gravity,
303387
int _verbose)
@@ -347,7 +431,26 @@ void mParticle::InitParticles(const Vector<Real>& x,
347431
mKernel.RL[1] = RLYt[real_index];
348432
mKernel.RL[2] = RLZt[real_index];
349433
mKernel.rho = rho_s[real_index];
434+
// geometry type
435+
if (geometry_type.size() > 0 && real_index < geometry_type.size()) {
436+
mKernel.geometry_type = geometry_type[real_index];
437+
} else {
438+
mKernel.geometry_type = 1; // default to sphere if not provided
439+
}
350440
mKernel.radius = radius[real_index];
441+
// ellipsoid particle need
442+
// Check if radius2 is provided and has enough elements
443+
if (radius2.size() > 0 && real_index < radius2.size()) {
444+
mKernel.radius2 = radius2[real_index];
445+
} else {
446+
mKernel.radius2 = radius[real_index]; // default to radius if not provided
447+
}
448+
// Check if radius3 is provided and has enough elements
449+
if (radius3.size() > 0 && real_index < radius3.size()) {
450+
mKernel.radius3 = radius3[real_index];
451+
} else {
452+
mKernel.radius3 = radius[real_index]; // default to radius if not provided
453+
}
351454
mKernel.Vp = Math::pi<Real>() * 4 / 3 * Math::powi<3>(radius[real_index]);
352455

353456
//int Ml = static_cast<int>( Math::pi<Real>() / 3 * (12 * Math::powi<2>(mKernel.radius / h)));
@@ -378,7 +481,7 @@ void mParticle::InitParticles(const Vector<Real>& x,
378481
if (verbose) amrex::Print() << "h: " << h << ", Ml: " << Ml << ", D: " << Math::powi<3>(h) << " gravity : " << gravity << "\n"
379482
<< "Kernel : " << index << ": Location (" << x[index] << ", " << y[index] << ", " << z[index]
380483
<< "), Velocity : (" << mKernel.velocity[0] << ", " << mKernel.velocity[1] << ", "<< mKernel.velocity[2]
381-
<< "), Radius: " << mKernel.radius << ", Ml: " << Ml << ", dv: " << dv << ", Rho: " << mKernel.rho << "\n";
484+
<< "), Radius: " << mKernel.radius << ", Radius2: " << mKernel.radius2 << ", Radius3: " << mKernel.radius3 << ", Ml: " << Ml << ", dv: " << dv << ", Rho: " << mKernel.rho << "\n";
382485
}
383486
//collision box generate
384487
m_Collision.SetGeometry(RealVect(ParticleProperties::GLO), RealVect(ParticleProperties::GHI),particle_kernels[0].radius, h);
@@ -791,12 +894,12 @@ void mParticle::UpdateParticles(int iStep,
791894
kernel.omega[idir] = kernel.omega_old[idir]
792895
+ ((kernel.sum_t_new[idir] - kernel.sum_t_old[idir]) * ParticleProperties::euler_fluid_rho / dt
793896
- kernel.ib_moment[idir] * ParticleProperties::euler_fluid_rho
794-
+ kernel.Tcp[idir]) * dt / cal_momentum(kernel.rho, kernel.radius);
897+
+ kernel.Tcp[idir]) * dt / cal_momentum(kernel.rho, kernel.radius, kernel.geometry_type, idir, kernel.radius2, kernel.radius3);
795898
}else{
796899
//Uhlmann
797900
kernel.omega[idir] = kernel.omega_old[idir]
798901
+ ParticleProperties::euler_fluid_rho /(ParticleProperties::euler_fluid_rho - kernel.rho) * kernel.ib_moment[idir] * kernel.dv
799-
/ cal_momentum(kernel.rho, kernel.radius) * kernel.rho * dt;
902+
/ cal_momentum(kernel.rho, kernel.radius, kernel.geometry_type, idir, kernel.radius2, kernel.radius3) * kernel.rho * dt;
800903
}
801904
}
802905
else {
@@ -1035,6 +1138,9 @@ void Particles::init_particle(Real gravity, Real h)
10351138
ParticleProperties::RLY,
10361139
ParticleProperties::RLZ,
10371140
ParticleProperties::_radius,
1141+
ParticleProperties::_radius2,
1142+
ParticleProperties::_radius3,
1143+
ParticleProperties::_geometry_type,
10381144
h,
10391145
gravity,
10401146
ParticleProperties::verbose);
@@ -1067,6 +1173,9 @@ void Particles::Restart(Real gravity, Real h, int iStep)
10671173
ParticleProperties::RLY,
10681174
ParticleProperties::RLZ,
10691175
ParticleProperties::_radius,
1176+
ParticleProperties::_radius2,
1177+
ParticleProperties::_radius3,
1178+
ParticleProperties::_geometry_type,
10701179
h,
10711180
gravity,
10721181
ParticleProperties::verbose);
@@ -1164,6 +1273,9 @@ void Particles::Initialize()
11641273
p_file.getarr("RLY", ParticleProperties::RLY);
11651274
p_file.getarr("RLZ", ParticleProperties::RLZ);
11661275
p_file.getarr("radius", ParticleProperties::_radius);
1276+
p_file.queryarr("radius2", ParticleProperties::_radius2);
1277+
p_file.queryarr("radius3", ParticleProperties::_radius3);
1278+
p_file.queryarr("geometry_type", ParticleProperties::_geometry_type);
11671279
p_file.query("RD", ParticleProperties::rd);
11681280
p_file.query("LOOP_NS", ParticleProperties::loop_ns);
11691281
p_file.query("LOOP_SOLID", ParticleProperties::loop_solid);

0 commit comments

Comments
 (0)