-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add quasi-3D Integrated Green Functions solver #5089
Changes from 72 commits
a7f3c75
e4b0d6a
da7bf7e
214c650
0841372
42db7c2
c334f39
e63eee4
4223920
f1cf0ee
3f463ea
ba0b02c
9b72d95
774de08
7553131
c0b3f4c
a7e3347
39c5983
e0f7d86
131c1bb
4086903
fc12321
15e6d82
2ff840b
e9f1bc2
b674324
da41a05
baaa72e
8f4684f
e198414
be4bbbc
9184eba
8c59a29
bc7d71f
b9c32ce
0e68679
ca5eefc
dd29a40
8885d18
0675d48
309b04e
5ff4fab
0407983
ba51c6d
1235219
d1ec79a
0255210
7069ca4
50f7b43
571ec8d
2a96941
d120936
da6ed73
fcd93aa
b060a89
33435d4
cb53fb7
6caf0cc
2b306fa
f46e3e2
ea41d4e
75af6a0
6fe9e07
f6b2b90
ffae96d
a00f974
690eddd
819f49a
688c4dc
963c4f6
b0686e7
d2406f8
1e2a239
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -290,6 +290,19 @@ Overall simulation parameters | |
In electromagnetic mode, this solver can be used to initialize the species' self fields | ||
(``<species_name>.initialize_self_fields=1``) provided that the field BCs are PML (``boundary.field_lo,hi = PML``). | ||
|
||
* warpx.use_2d_slices_fft_solver (`bool`, default: 0): Select the type of Integrated Green Function solver. | ||
If 0, solve Poisson equation in full 3D geometry. | ||
If 1, solve Poisson equation in a quasi 3D geometry, neglecting the :math:`z` derivatives in the Laplacian of the Poisson equation. | ||
In practice, in this case, the code performes many 2D Poisson solves on all :math:`(x,y)` slices, each slice at a given :math:`z`. | ||
This is often a good approximation for ultra-relativistic beams propagating along the :math:`z` direction, with the relativistic solver. | ||
As a consequence, this solver does not need to do an FFT along the :math:`z` direction, | ||
and instead uses only transverse FFTs (along :math:`x` and :math:`y`) at each :math:`z` position (or :math:`z` "slice"). | ||
|
||
* warpx.use_distributed_3d_fft_solver (`bool`, default: 0): Choose whether the 3D FFTs performed in the | ||
full 3D Integrated Green Function solver are distributed. | ||
If 0, the FFTs are performed on a single MPI rank (the rest of the code is still fully parallel). | ||
If 1, the FFTs are distributed using the heFFTe library. The code must be compiled with `-DWarpX_HEFFTE=ON`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you remove this? It seems that it is not actually used in the code. |
||
|
||
* ``warpx.self_fields_required_precision`` (`float`, default: 1.e-11) | ||
The relative precision with which the electrostatic space-charge fields should | ||
be calculated. More specifically, the space-charge fields are | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FILE = inputs_test_3d_open_bc_poisson_solver | ||
|
||
warpx.use_2d_slices_fft_solver = 1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. Didn't we already have a checksum file for this test before? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought so too, but there isn't one in development right now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, from here it seems like that the checksums were saved in the wrong file, overwriting the ones for the test without That also explains why I had to change There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you remove this |
||
"lev=0": { | ||
"Bx": 100915933.44552392, | ||
"By": 157610622.18550807, | ||
"Bz": 8.739731456892512e-12, | ||
"Ex": 4.725065270619816e+16, | ||
"Ey": 3.025394898923131e+16, | ||
"Ez": 3276573.95147766, | ||
"rho": 10994013582437.193 | ||
}, | ||
"electron": { | ||
"particle_momentum_x": 5.701277606055911e-19, | ||
"particle_momentum_y": 3.650451663619896e-19, | ||
"particle_momentum_z": 1.145432768297242e-10, | ||
"particle_position_x": 17.314086912497864, | ||
"particle_position_y": 0.2583691267187796, | ||
"particle_position_z": 10066.329600000008, | ||
"particle_weight": 19969036501.910976 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"lev=0": { | ||
"Bx": 100915933.44551668, | ||
"By": 157610622.18551716, | ||
"Bz": 2.598515299403035e-15, | ||
"Ex": 4.725065270620093e+16, | ||
"Ey": 3.0253948989229424e+16, | ||
"Ez": 2787743.3330717986, | ||
"rho": 10994013582437.193 | ||
}, | ||
"electron": { | ||
"particle_momentum_x": 5.701277606056779e-19, | ||
"particle_momentum_y": 3.650451663675671e-19, | ||
"particle_momentum_z": 1.145432768297242e-10, | ||
"particle_position_x": 17.314086912497864, | ||
"particle_position_y": 0.25836912671877954, | ||
"particle_position_z": 10066.329600000008, | ||
"particle_weight": 19969036501.910976 | ||
} | ||
} | ||
|
aeriforme marked this conversation as resolved.
Show resolved
Hide resolved
|
aeriforme marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -15,13 +15,14 @@ | |||||
#include <AMReX_REAL.H> | ||||||
#include <AMReX_Vector.H> | ||||||
|
||||||
|
||||||
#include <array> | ||||||
#include <cmath> | ||||||
|
||||||
|
||||||
namespace ablastr::fields | ||||||
{ | ||||||
using namespace amrex::literals; | ||||||
|
||||||
|
||||||
/** @brief Implements equation 2 in https://doi.org/10.1103/PhysRevSTAB.10.129901 | ||||||
* with some modification to symmetrize the function. | ||||||
|
@@ -30,54 +31,92 @@ namespace ablastr::fields | |||||
* @param[in] y y-coordinate of given location | ||||||
* @param[in] z z-coordinate of given location | ||||||
* | ||||||
* @return the integrated Green function G | ||||||
* @return the integrated Green function G in 3D | ||||||
*/ | ||||||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||||||
amrex::Real | ||||||
IntegratedPotential (amrex::Real x, amrex::Real y, amrex::Real z) | ||||||
IntegratedPotential3D (amrex::Real x, amrex::Real y, amrex::Real z) | ||||||
{ | ||||||
using namespace amrex::literals; | ||||||
|
||||||
amrex::Real const r = std::sqrt( x*x + y*y + z*z ); | ||||||
amrex::Real const G = | ||||||
- 0.5_rt * z*z * std::atan( x*y/(z*r) ) | ||||||
- 0.5_rt * y*y * std::atan( x*z/(y*r) ) | ||||||
- 0.5_rt * x*x * std::atan( y*z/(x*r) ) | ||||||
+ y*z*std::asinh( x/std::sqrt(y*y + z*z) ) | ||||||
+ x*z*std::asinh( y/std::sqrt(x*x + z*z) ) | ||||||
+ x*y*std::asinh( z/std::sqrt(x*x + y*y) ); | ||||||
amrex::Real const G = - 0.5_rt * z*z * std::atan( x*y/(z*r) ) | ||||||
- 0.5_rt * y*y * std::atan( x*z/(y*r) ) | ||||||
- 0.5_rt * x*x * std::atan( y*z/(x*r) ) | ||||||
+ y*z*std::asinh( x/std::sqrt(y*y + z*z) ) | ||||||
+ x*z*std::asinh( y/std::sqrt(x*x + z*z) ) | ||||||
+ x*y*std::asinh( z/std::sqrt(x*x + y*y) ); | ||||||
return G; | ||||||
} | ||||||
|
||||||
|
||||||
/** @brief Implements minus equation 58 in https://doi.org/10.1016/j.jcp.2004.01.008 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think I understand what is meant here, but the term "minus equation" might be confusing. I think it is fine to simply say "equation 58". |
||||||
* | ||||||
* @param[in] x x-coordinate of given location | ||||||
* @param[in] y y-coordinate of given location | ||||||
* | ||||||
* @return the integrated Green function G in 2D | ||||||
*/ | ||||||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||||||
amrex::Real | ||||||
IntegratedPotential2D (amrex::Real x, amrex::Real y) | ||||||
{ | ||||||
amrex::Real const G = 3_rt*x*y | ||||||
- x*x * std::atan(y/x) | ||||||
- y*y * std::atan(x/y) | ||||||
- x*y * std::log(x*x + y*y); | ||||||
return G; | ||||||
} | ||||||
|
||||||
|
||||||
/** @brief add | ||||||
* | ||||||
* @param[in] x x-coordinate of given location | ||||||
* @param[in] y y-coordinate of given location | ||||||
* @param[in] z z-coordinate of given location | ||||||
* @param[in] dx cell size along x | ||||||
* @param[in] dy cell size along y | ||||||
* @param[in] dz cell size along z | ||||||
* | ||||||
* @return the sum of integrated Green function G | ||||||
* @return the sum of integrated Green function G in 3D | ||||||
*/ | ||||||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||||||
amrex::Real | ||||||
SumOfIntegratedPotential (amrex::Real x, amrex::Real y, amrex::Real z, amrex::Real dx, amrex::Real dy, amrex::Real dz) | ||||||
SumOfIntegratedPotential3D (amrex::Real x, amrex::Real y, amrex::Real z, amrex::Real dx, amrex::Real dy, amrex::Real dz) | ||||||
{ | ||||||
using namespace amrex::literals; | ||||||
|
||||||
return 1._rt/(4._rt*ablastr::constant::math::pi*ablastr::constant::SI::ep0) * ( | ||||||
IntegratedPotential3D( x+0.5_rt*dx, y+0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential3D( x-0.5_rt*dx, y+0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential3D( x+0.5_rt*dx, y-0.5_rt*dy, z+0.5_rt*dz ) | ||||||
+ IntegratedPotential3D( x-0.5_rt*dx, y-0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential3D( x+0.5_rt*dx, y+0.5_rt*dy, z-0.5_rt*dz ) | ||||||
+ IntegratedPotential3D( x-0.5_rt*dx, y+0.5_rt*dy, z-0.5_rt*dz ) | ||||||
+ IntegratedPotential3D( x+0.5_rt*dx, y-0.5_rt*dy, z-0.5_rt*dz ) | ||||||
- IntegratedPotential3D( x-0.5_rt*dx, y-0.5_rt*dy, z-0.5_rt*dz ) | ||||||
); | ||||||
} | ||||||
|
||||||
amrex::Real const G_value = 1._rt/(4._rt*ablastr::constant::math::pi*ablastr::constant::SI::ep0) * ( | ||||||
IntegratedPotential( x+0.5_rt*dx, y+0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential( x-0.5_rt*dx, y+0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential( x+0.5_rt*dx, y-0.5_rt*dy, z+0.5_rt*dz ) | ||||||
+ IntegratedPotential( x-0.5_rt*dx, y-0.5_rt*dy, z+0.5_rt*dz ) | ||||||
- IntegratedPotential( x+0.5_rt*dx, y+0.5_rt*dy, z-0.5_rt*dz ) | ||||||
+ IntegratedPotential( x-0.5_rt*dx, y+0.5_rt*dy, z-0.5_rt*dz ) | ||||||
+ IntegratedPotential( x+0.5_rt*dx, y-0.5_rt*dy, z-0.5_rt*dz ) | ||||||
- IntegratedPotential( x-0.5_rt*dx, y-0.5_rt*dy, z-0.5_rt*dz ) | ||||||
); | ||||||
|
||||||
return G_value; | ||||||
/** @brief add | ||||||
* | ||||||
* @param[in] x x-coordinate of given location | ||||||
* @param[in] y y-coordinate of given location | ||||||
* @param[in] dx cell size along x | ||||||
* @param[in] dy cell size along y | ||||||
* | ||||||
* @return the sum of integrated Green function G in 2D | ||||||
*/ | ||||||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||||||
amrex::Real | ||||||
SumOfIntegratedPotential2D (amrex::Real x, amrex::Real y, amrex::Real dx, amrex::Real dy) | ||||||
{ | ||||||
return 1._rt/(4._rt*ablastr::constant::math::pi*ablastr::constant::SI::ep0) * ( | ||||||
IntegratedPotential2D( x+0.5_rt*dx, y+0.5_rt*dy ) | ||||||
- IntegratedPotential2D( x+0.5_rt*dx, y-0.5_rt*dy ) | ||||||
- IntegratedPotential2D( x-0.5_rt*dx, y+0.5_rt*dy ) | ||||||
+ IntegratedPotential2D( x-0.5_rt*dx, y-0.5_rt*dy ) | ||||||
); | ||||||
} | ||||||
|
||||||
|
||||||
/** @brief Compute the electrostatic potential using the Integrated Green Function method | ||||||
* as in http://dx.doi.org/10.1103/PhysRevSTAB.9.044204 | ||||||
* | ||||||
|
@@ -90,7 +129,8 @@ namespace ablastr::fields | |||||
computePhiIGF (amrex::MultiFab const & rho, | ||||||
amrex::MultiFab & phi, | ||||||
std::array<amrex::Real, 3> const & cell_size, | ||||||
amrex::BoxArray const & ba); | ||||||
amrex::BoxArray const & ba, | ||||||
bool do_2d_slices); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to use the same name ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, sure! |
||||||
|
||||||
} // namespace ablastr::fields | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,8 @@ void | |
computePhiIGF ( amrex::MultiFab const & rho, | ||
amrex::MultiFab & phi, | ||
std::array<amrex::Real, 3> const & cell_size, | ||
amrex::BoxArray const & ba) | ||
amrex::BoxArray const & ba, | ||
bool const do_2d_slices) | ||
{ | ||
using namespace amrex::literals; | ||
|
||
|
@@ -45,9 +46,6 @@ computePhiIGF ( amrex::MultiFab const & rho, | |
domain.surroundingNodes(); // get nodal points, since `phi` and `rho` are nodal | ||
domain.grow( phi.nGrowVect() ); // include guard cells | ||
|
||
// Do we grow the domain in the z-direction in the 2D mode? | ||
bool const do_2d_fft = false; | ||
|
||
int nprocs = amrex::ParallelDescriptor::NProcs(); | ||
{ | ||
amrex::ParmParse pp("ablastr"); | ||
|
@@ -61,7 +59,7 @@ computePhiIGF ( amrex::MultiFab const & rho, | |
} | ||
if (!obc_solver || obc_solver->Domain() != domain) { | ||
amrex::FFT::Info info{}; | ||
if (do_2d_fft) { info.setBatchMode(true); } | ||
if (do_2d_slices) { info.setBatchMode(true); } // do 2D FFTs | ||
info.setNumProcs(nprocs); | ||
obc_solver = std::make_unique<amrex::FFT::OpenBCSolver<amrex::Real>>(domain, info); | ||
} | ||
|
@@ -71,7 +69,9 @@ computePhiIGF ( amrex::MultiFab const & rho, | |
amrex::Real const dy = cell_size[1]; | ||
amrex::Real const dz = cell_size[2]; | ||
|
||
obc_solver->setGreensFunction( | ||
if (!do_2d_slices){ | ||
// 2D sliced solver | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment here and the one in the else part are incorrect. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops! I will fix it |
||
obc_solver->setGreensFunction( | ||
[=] AMREX_GPU_DEVICE (int i, int j, int k) -> amrex::Real | ||
{ | ||
int const i0 = i - lo[0]; | ||
|
@@ -80,9 +80,26 @@ computePhiIGF ( amrex::MultiFab const & rho, | |
amrex::Real const x = i0*dx; | ||
amrex::Real const y = j0*dy; | ||
amrex::Real const z = k0*dz; | ||
return SumOfIntegratedPotential(x, y, z, dx, dy, dz); | ||
|
||
return SumOfIntegratedPotential3D(x, y, z, dx, dy, dz); | ||
}); | ||
}else{ | ||
// fully 3D solver | ||
obc_solver->setGreensFunction( | ||
[=] AMREX_GPU_DEVICE (int i, int j, int k) -> amrex::Real | ||
{ | ||
int const i0 = i - lo[0]; | ||
int const j0 = j - lo[1]; | ||
amrex::Real const x = i0*dx; | ||
amrex::Real const y = j0*dy; | ||
amrex::ignore_unused(k); | ||
|
||
return SumOfIntegratedPotential2D(x, y, dx, dy); | ||
}); | ||
|
||
} | ||
|
||
obc_solver->solve(phi, rho); | ||
} | ||
} // computePhiIGF | ||
|
||
} // namespace ablastr::fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.