IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
NonStandardFDTDSolver.hpp
Go to the documentation of this file.
1
5
6namespace ippl {
7
19 template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
21 SourceField& source, EMField& E, EMField& B)
22 : FDTDSolverBase<EMField, SourceField, boundary_conditions>(source, E, B) {
23 auto hx = source.get_mesh().getMeshSpacing();
24 if ((hx[2] / hx[0]) * (hx[2] / hx[0]) + (hx[2] / hx[1]) * (hx[2] / hx[1]) >= 1) {
25 throw IpplException("NonStandardFDTDSolver Constructor",
26 "Dispersion-free CFL condition not satisfiable\n");
27 }
28 initialize();
29 }
30
38 template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
40 const auto& ldom = this->layout_mp->getLocalNDIndex();
41 const int nghost = this->A_n.getNghost();
42 const auto aview = this->A_n.getView();
43 const auto anp1view = this->A_np1.getView();
44 const auto anm1view = this->A_nm1.getView();
45 const auto source_view = Maxwell<EMField, SourceField>::JN_mp->getView();
46
47 const scalar calA =
48 0.25
49 * (1
50 + 0.02
51 / (static_cast<scalar>(Kokkos::pow(this->hr_m[2] / this->hr_m[0], 2))
52 + static_cast<scalar>(Kokkos::pow(this->hr_m[2] / this->hr_m[1], 2))));
54 .a1 =
55 2
56 * (1
57 - (1 - 2 * calA) * static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[0], 2))
58 - (1 - 2 * calA) * static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[1], 2))
59 - static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[2], 2))),
60 .a2 = static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[0], 2)),
61 .a4 = static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[1], 2)),
62 .a6 = static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[2], 2))
63 - 2 * calA * static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[0], 2))
64 - 2 * calA * static_cast<scalar>(Kokkos::pow(this->dt / this->hr_m[1], 2)),
65 .a8 = static_cast<scalar>(Kokkos::pow(this->dt, 2))};
66 Vector<uint32_t, Dim> true_nr = this->nr_m;
67 true_nr += (nghost * 2);
68 constexpr uint32_t one_if_absorbing_otherwise_0 =
69 boundary_conditions == absorbing
70 ? 1
71 : 0; // 1 if absorbing, 0 otherwise, indicates the start index of the field
72 Kokkos::parallel_for(
73 ippl::getRangePolicy(aview, nghost), KOKKOS_LAMBDA(size_t i, size_t j, size_t k) {
74 // global indices
75 uint32_t ig = i + ldom.first()[0];
76 uint32_t jg = j + ldom.first()[1];
77 uint32_t kg = k + ldom.first()[2];
78 // check if at a boundary of the field
79 uint32_t val =
80 uint32_t(ig == one_if_absorbing_otherwise_0)
81 + (uint32_t(jg == one_if_absorbing_otherwise_0) << 1)
82 + (uint32_t(kg == one_if_absorbing_otherwise_0) << 2)
83 + (uint32_t(ig == true_nr[0] - one_if_absorbing_otherwise_0 - 1) << 3)
84 + (uint32_t(jg == true_nr[1] - one_if_absorbing_otherwise_0 - 1) << 4)
85 + (uint32_t(kg == true_nr[2] - one_if_absorbing_otherwise_0 - 1) << 5);
86 // update the interior field values
87 if (!val) {
88 anp1view(i, j, k) =
89 -anm1view(i, j, k) + ndisp.a1 * aview(i, j, k)
90 + ndisp.a2
91 * (calA * aview(i + 1, j, k - 1) + (1 - 2 * calA) * aview(i + 1, j, k)
92 + calA * aview(i + 1, j, k + 1))
93 + ndisp.a2
94 * (calA * aview(i - 1, j, k - 1) + (1 - 2 * calA) * aview(i - 1, j, k)
95 + calA * aview(i - 1, j, k + 1))
96 + ndisp.a4
97 * (calA * aview(i, j + 1, k - 1) + (1 - 2 * calA) * aview(i, j + 1, k)
98 + calA * aview(i, j + 1, k + 1))
99 + ndisp.a4
100 * (calA * aview(i, j - 1, k - 1) + (1 - 2 * calA) * aview(i, j - 1, k)
101 + calA * aview(i, j - 1, k + 1))
102 + ndisp.a6 * aview(i, j, k + 1) + ndisp.a6 * aview(i, j, k - 1)
103 + ndisp.a8 * source_view(i, j, k);
104 }
105 });
106 Kokkos::fence();
107 this->A_np1.fillHalo();
108 this->applyBCs();
109 }
110
117 template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
119 // get layout and mesh
120 this->layout_mp = &(this->JN_mp->getLayout());
121 this->mesh_mp = &(this->JN_mp->get_mesh());
122
123 // get mesh spacing, domain, and mesh size
124 this->hr_m = this->mesh_mp->getMeshSpacing();
125 this->dt = this->hr_m[2];
126 this->domain_m = this->layout_mp->getDomain();
127 for (unsigned int i = 0; i < Dim; ++i)
128 this->nr_m[i] = this->domain_m[i].length();
129
130 // initialize fields
131 this->A_nm1.initialize(*this->mesh_mp, *this->layout_mp);
132 this->A_n.initialize(*this->mesh_mp, *this->layout_mp);
133 this->A_np1.initialize(*this->mesh_mp, *this->layout_mp);
134
135 this->A_nm1 = 0.0;
136 this->A_n = 0.0;
137 this->A_np1 = 0.0;
138
139 // set the mesh domain
140 if constexpr (boundary_conditions == periodic) {
142 }
143 };
144} // namespace ippl
Definition Archive.h:20
RangePolicy< View::rank, typenameView::execution_space, PolicyArgs... >::policy_type getRangePolicy(const View &view, int shift=0)
FDTDSolverBase(SourceField &source, EMField &E, EMField &B)
SourceField * JN_mp
Definition Maxwell.h:77
static constexpr unsigned Dim
void step() override
Advances the simulation by one time step.
NonStandardFDTDSolver(SourceField &source, EMField &E, EMField &B)
Constructs a NonStandardFDTDSolver.
void initialize() override
Initializes the solver.
typename EMField::value_type::value_type scalar
A structure representing nondispersive coefficients.