-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.cpp
233 lines (195 loc) · 7.15 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// -*- C++ -*-
#include "diagnoser.hpp"
#include "expic3d.hpp"
#include "nix/random.hpp"
constexpr int order = PICNIX_SHAPE_ORDER;
class MainChunk;
class MainApplication;
using MainDiagnoser = Diagnoser;
class MainChunk : public ExChunk3D<order>
{
public:
using ExChunk3D<order>::ExChunk3D; // inherit constructors
virtual void setup(json& config) override
{
ExChunk3D<order>::setup(config);
// check validity of assumptions
{
constexpr int Ns_mustbe = 3;
Ns = config["Ns"].get<int>();
if (Ns != Ns_mustbe) {
ERROR << "Assumption of Ns = 3 is violated";
exit(-1);
}
}
// speed of light
cc = config["cc"].get<float64>();
int nppc = config["nppc"].get<int>();
float64 wp = config["wp"].get<float64>();
float64 delt = config["delt"].get<float64>();
float64 delh = config["delh"].get<float64>();
float64 mime = config["mime"].get<float64>();
float64 ush = config["ush"].get<float64>();
float64 theta = config["theta"].get<float64>();
float64 phi = config["phi"].get<float64>();
float64 sigma = config["sigma"].get<float64>();
float64 alpha = config["alpha"].get<float64>();
float64 betae = config["betae"].get<float64>();
float64 betai = config["betai"].get<float64>();
float64 betar = config["betar"].get<float64>();
float64 gamsh = sqrt(1.0 + (ush * ush) / (cc * cc));
float64 me = 1.0 / nppc;
float64 qe = -wp / nppc;
float64 mi = me * mime;
float64 qi = -qe;
float64 b0 = cc * wp * sqrt(sigma) / std::abs(qe / me);
float64 vae = cc * sqrt(sigma);
float64 vai = cc * sqrt(sigma / mime);
float64 vte = vae * sqrt(0.5 * betae);
float64 vti = vai * sqrt(0.5 * betai);
float64 vtr = vai * sqrt(0.5 * betar);
// quantities in the simulation frame
float64 vsh = ush / gamsh;
float64 vdi = -2 * alpha * vsh / (1 - (1 - 2 * alpha) * vsh * vsh);
float64 vdr = +2 * (1 - alpha) * vsh / (1 + (1 - 2 * alpha) * vsh * vsh);
float64 udi = vdi / sqrt(1 - vdi * vdi / (cc * cc));
float64 udr = vdr / sqrt(1 - vdr * vdr / (cc * cc));
float64 nref = alpha * (1 + (1 - 2 * alpha) * vsh * vsh) /
(1 - (1 - 2 * alpha) * (1 - 2 * alpha) * vsh * vsh);
// set grid size and coordinate
set_coordinate(delh, delh, delh);
//
// initialize field
//
{
float64 Bx = b0 * cos(theta / 180 * nix::math::pi);
float64 By = b0 * sin(theta / 180 * nix::math::pi) * cos(phi / 180 * nix::math::pi);
float64 Bz = b0 * sin(theta / 180 * nix::math::pi) * sin(phi / 180 * nix::math::pi);
// memory allocation
allocate();
for (int iz = Lbz; iz <= Ubz; iz++) {
for (int iy = Lby; iy <= Uby; iy++) {
for (int ix = Lbx; ix <= Ubx; ix++) {
uf(iz, iy, ix, 0) = 0;
uf(iz, iy, ix, 1) = 0;
uf(iz, iy, ix, 2) = 0;
uf(iz, iy, ix, 3) = Bx;
uf(iz, iy, ix, 4) = By;
uf(iz, iy, ix, 5) = Bz;
}
}
}
// allocate MPI buffer for field
this->set_mpi_buffer(mpibufvec[BoundaryEmf], 0, 0, sizeof(float64) * 6);
this->set_mpi_buffer(mpibufvec[BoundaryCur], 0, 0, sizeof(float64) * 4);
this->set_mpi_buffer(mpibufvec[BoundaryMom], 0, 0, sizeof(float64) * Ns * 11);
// setup for Friedman filter
this->setup_friedman_filter();
}
//
// initialize particles
//
{
int random_seed = option["random_seed"].get<int>();
std::mt19937_64 mtp(random_seed);
std::mt19937_64 mtv(random_seed);
nix::rand_uniform uniform(0.0, 1.0);
nix::MaxwellJuttner mj_ele(vte * vte, 0.0);
std::vector<nix::MaxwellJuttner> mj_ion;
mj_ion.push_back(nix::MaxwellJuttner(vti * vti, udi));
mj_ion.push_back(nix::MaxwellJuttner(vtr * vtr, udr));
{
int nz = dims[0] + 2 * Nb;
int ny = dims[1] + 2 * Nb;
int nx = dims[2] + 2 * Nb;
int mp = nppc * dims[0] * dims[1] * dims[2];
int mp1 = mp * (1 - nref);
int mp2 = mp - mp1;
int64 id = static_cast<int64>(mp) * static_cast<int64>(this->myid);
up.resize(Ns);
// electron
up[0] = std::make_shared<ParticleType>(2 * mp, nz * ny * nx);
up[0]->m = me;
up[0]->q = qe;
up[0]->Np = mp;
// incoming ion
up[1] = std::make_shared<ParticleType>(2 * mp1, nz * ny * nx);
up[1]->m = mi;
up[1]->q = qi;
up[1]->Np = mp1;
// reflected ion
up[2] = std::make_shared<ParticleType>(2 * mp2, nz * ny * nx);
up[2]->m = mi;
up[2]->q = qi;
up[2]->Np = mp2;
// initialize particle distribution
std::vector<int> mp_ele{0, mp1};
std::vector<int> mp_ion{mp1, mp2};
for (int is = 0; is < 2; is++) {
const int is_ele = 0;
const int is_ion = is + 1;
const int ip_ele_zero = mp_ele[is];
const int ip_ion_zero = 0;
for (int ip = 0; ip < mp_ion[is]; ip++) {
const int ip_ele = ip + ip_ele_zero;
const int ip_ion = ip + ip_ion_zero;
// position: using these guarantees charge neutrality
float64 x = uniform(mtp) * xlim[2] + xlim[0];
float64 y = uniform(mtp) * ylim[2] + ylim[0];
float64 z = uniform(mtp) * zlim[2] + zlim[0];
// electrons
{
auto [ux, uy, uz] = mj_ele(mtv);
up[is_ele]->xu(ip_ele, 0) = x;
up[is_ele]->xu(ip_ele, 1) = y;
up[is_ele]->xu(ip_ele, 2) = z;
up[is_ele]->xu(ip_ele, 3) = ux;
up[is_ele]->xu(ip_ele, 4) = uy;
up[is_ele]->xu(ip_ele, 5) = uz;
}
// ions
{
auto [ux, uy, uz] = mj_ion[is](mtv);
up[is_ion]->xu(ip_ion, 0) = x;
up[is_ion]->xu(ip_ion, 1) = y;
up[is_ion]->xu(ip_ion, 2) = z;
up[is_ion]->xu(ip_ion, 3) = ux;
up[is_ion]->xu(ip_ion, 4) = uy;
up[is_ion]->xu(ip_ion, 5) = uz;
}
// ID
int64* ele_id64 = reinterpret_cast<int64*>(&up[is_ele]->xu(ip_ele, 0));
int64* ion_id64 = reinterpret_cast<int64*>(&up[is_ion]->xu(ip_ion, 0));
ele_id64[6] = id + ip_ele;
ion_id64[6] = id + ip_ele;
}
}
}
// initial sort
this->sort_particle(up);
// allocate MPI buffer for particle
setup_particle_mpi_buffer(option["mpi_buffer_fraction"].get<float64>());
}
}
};
class MainApplication : public ExPIC3D<MainChunk, MainDiagnoser>
{
public:
using ExPIC3D<MainChunk, MainDiagnoser>::ExPIC3D; // inherit constructors
std::unique_ptr<MainChunk> create_chunk(const int dims[], int id) override
{
return std::make_unique<MainChunk>(dims, id);
}
};
//
// main
//
int main(int argc, char** argv)
{
MainApplication app(argc, argv);
return app.main();
}
// Local Variables:
// c-file-style : "gnu"
// c-file-offsets : ((innamespace . 0) (inline-open . 0))
// End: