Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
ldz_main.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
45
48#include "ldz_hall.hpp"
49#include "ldz_gradpe.hpp"
50#include "ldz_volume.hpp"
51#include "fs_common.h"
52#include "derivatives.hpp"
53#include "fs_limiters.h"
54#include "mpiconversion.h"
56#include "../logger.h"
57extern Logger logFile;
58
92 fsgrids::perbspan perbdt2,
97 fsgrids::egradpespan egradpedt2,
99 fsgrids::momentsspan momentsdt2,
100 fsgrids::dperbspan dperb,
101 fsgrids::dmomentsspan dmoments,
102 fsgrids::dmomentsspan dmomentsdt2,
105 fsgrids::technicalspan technical,
107 SysBoundary& sysBoundaries,
108 creal& dt,
109 cuint subcycles) {
110
111 if (subcycles == 0) {
112 cerr << "Field solver subcycles cannot be 0." << endl;
113 exit(1);
114 }
115
116 const auto* localSize = &fsgrid.getLocalSize()[0];
117
118 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
119 phiprof::initializeTimer("Initialize technical.maxFsDt"), technical,
120 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
121 technical[stencil.ooo()].maxFsDt = std::numeric_limits<Real>::max();
122 });
123
124 if (subcycles == 1) {
125#ifdef FS_1ST_ORDER_TIME
126 propagateMagneticFieldSimple(perb, perbdt2, bgb, e, edt2, technical, fsgrid, sysBoundaries, dt, RK_ORDER1);
127 calculateDerivativesSimple(perb, moments, dperb, dmoments, technical, fsgrid, true /*doMoments*/);
128 if (P::ohmGradPeTerm > 0) {
129 calculateGradPeTermSimple(egradpe, egradpedt2, moments, momentsdt2, dmoments, dmomentsdt2, technical, fsgrid, sysBoundaries, RK_ORDER1);
130 }
131 if (P::ohmHallTerm > 0) {
133 perb,
134 perbdt2,
135 ehall,
136 moments,
137 momentsdt2,
138 dperb,
139 dmoments,
140 dmomentsdt2,
141 bgb,
142 technical,
143 fsgrid,
144 sysBoundaries,
145 RK_ORDER1,
146 true // communicateMomentsDerivatives
147 );
148 }
150 perb,
151 perbdt2,
152 e,
153 edt2,
154 ehall,
155 egradpe,
156 egradpedt2,
157 moments,
158 momentsdt2,
159 dperb,
160 dmoments,
161 dmomentsdt2,
162 bgb,
163 technical,
164 fsgrid,
165 sysBoundaries,
166 RK_ORDER1,
167 true // communicateEGradPeOrMomentsDerivatives
168 );
169#else
170 propagateMagneticFieldSimple(perb, perbdt2, bgb, e, edt2, technical, fsgrid, sysBoundaries, dt, RK_ORDER2_STEP1);
171 calculateDerivativesSimple(perbdt2, momentsdt2, dperb, dmomentsdt2, technical, fsgrid, true /*doMoments*/);
172 if (P::ohmGradPeTerm > 0) {
173 calculateGradPeTermSimple(egradpe, egradpedt2, moments, momentsdt2, dmoments, dmomentsdt2, technical, fsgrid, sysBoundaries, RK_ORDER2_STEP1);
174 }
175 if (P::ohmHallTerm > 0) {
177 perb,
178 perbdt2,
179 ehall,
180 moments,
181 momentsdt2,
182 dperb,
183 dmoments,
184 dmomentsdt2,
185 bgb,
186 technical,
187 fsgrid,
188 sysBoundaries,
190 true // communicateMomentsDerivatives
191 );
192 }
194 perb,
195 perbdt2,
196 e,
197 edt2,
198 ehall,
199 egradpe,
200 egradpedt2,
201 moments,
202 momentsdt2,
203 dperb,
204 dmoments,
205 dmomentsdt2,
206 bgb,
207 technical,
208 fsgrid,
209 sysBoundaries,
211 true // communicateEGradPeOrMomentsDerivatives
212 );
213
214 propagateMagneticFieldSimple(perb, perbdt2, bgb, e, edt2, technical, fsgrid, sysBoundaries, dt, RK_ORDER2_STEP2);
215 calculateDerivativesSimple(perb, moments, dperb, dmoments, technical, fsgrid, true /*doMoments*/);
216 if (P::ohmGradPeTerm > 0) {
217 calculateGradPeTermSimple(egradpe, egradpedt2, moments, momentsdt2, dmoments, dmomentsdt2, technical, fsgrid, sysBoundaries, RK_ORDER2_STEP2);
218 }
219 if (P::ohmHallTerm > 0) {
221 perb,
222 perbdt2,
223 ehall,
224 moments,
225 momentsdt2,
226 dperb,
227 dmoments,
228 dmomentsdt2,
229 bgb,
230 technical,
231 fsgrid,
232 sysBoundaries,
234 true // communicateMomentsDerivatives
235 );
236 }
238 perb,
239 perbdt2,
240 e,
241 edt2,
242 ehall,
243 egradpe,
244 egradpedt2,
245 moments,
246 momentsdt2,
247 dperb,
248 dmoments,
249 dmomentsdt2,
250 bgb,
251 technical,
252 fsgrid,
253 sysBoundaries,
255 true // communicateEGradPeOrMomentsDerivatives
256 );
257#endif
258 } else {
259 Real subcycleDt = dt / convert<Real>(subcycles);
260 Real subcycleT = P::t;
261 creal targetT = P::t + dt;
262 uint subcycleCount = 0;
263 uint maxSubcycleCount = std::numeric_limits<uint>::max();
264 int myRank = fsgrid.getRank();
265
266 while (subcycleCount < maxSubcycleCount) {
267 // In case of subcycling, we decided to go for a blunt Runge-Kutta subcycling even though e.g. moments are not
268 // going along. Result of the Summer of Debugging 2016, the behaviour in wave dispersion was much improved with
269 // this.
270 propagateMagneticFieldSimple(perb, perbdt2, bgb, e, edt2, technical, fsgrid, sysBoundaries, subcycleDt, RK_ORDER2_STEP1);
271
272 // We need to calculate derivatives of the moments at every substep, but the moments only
273 // need to be communicated in the first one.
274 calculateDerivativesSimple(perbdt2, momentsdt2, dperb, dmomentsdt2, technical, fsgrid, (subcycleCount == 0) /*doMoments*/);
275 if (P::ohmGradPeTerm > 0 && subcycleCount == 0) {
276 calculateGradPeTermSimple(egradpe, egradpedt2, moments, momentsdt2, dmoments, dmomentsdt2, technical, fsgrid, sysBoundaries, RK_ORDER2_STEP1);
277 }
278 if (P::ohmHallTerm > 0) {
280 perb,
281 perbdt2,
282 ehall,
283 moments,
284 momentsdt2,
285 dperb,
286 dmoments,
287 dmomentsdt2,
288 bgb,
289 technical,
290 fsgrid,
291 sysBoundaries,
293 subcycleCount == 0 // communicateMomentsDerivatives
294 );
295 }
297 perb,
298 perbdt2,
299 e,
300 edt2,
301 ehall,
302 egradpe,
303 egradpedt2,
304 moments,
305 momentsdt2,
306 dperb,
307 dmoments,
308 dmomentsdt2,
309 bgb,
310 technical,
311 fsgrid,
312 sysBoundaries,
314 subcycleCount == 0 // communicateEGradPeOrMomentsDerivatives
315 );
316
317 propagateMagneticFieldSimple(perb, perbdt2, bgb, e, edt2, technical, fsgrid, sysBoundaries, subcycleDt, RK_ORDER2_STEP2);
318
319 // We need to calculate derivatives of the moments at every substep, but the moments only
320 // need to be communicated in the first one.
321 calculateDerivativesSimple(perb, moments, dperb, dmoments, technical, fsgrid, (subcycleCount == 0) /*doMoments*/);
322 if (P::ohmGradPeTerm > 0 && subcycleCount == 0) {
323 calculateGradPeTermSimple(egradpe, egradpedt2, moments, momentsdt2, dmoments, dmomentsdt2, technical, fsgrid, sysBoundaries, RK_ORDER2_STEP2);
324 }
325 if (P::ohmHallTerm > 0) {
327 perb,
328 perbdt2,
329 ehall,
330 moments,
331 momentsdt2,
332 dperb,
333 dmoments,
334 dmomentsdt2,
335 bgb,
336 technical,
337 fsgrid,
338 sysBoundaries,
340 subcycleCount == 0 // communicateMomentsDerivatives
341 );
342 }
344 perb,
345 perbdt2,
346 e,
347 edt2,
348 ehall,
349 egradpe,
350 egradpedt2,
351 moments,
352 momentsdt2,
353 dperb,
354 dmoments,
355 dmomentsdt2,
356 bgb,
357 technical,
358 fsgrid,
359 sysBoundaries,
361 subcycleCount == 0 // communicateEGradPeOrMomentsDerivatives
362 );
363
364 phiprof::Timer subcyclingTimer{"FS subcycle stuff"};
365 subcycleT += subcycleDt;
366 subcycleCount++;
367
368 if (subcycleT >= targetT || subcycleCount >= maxSubcycleCount) {
369 // we are done
370 if (subcycleT > targetT) {
371 // due to roundoff we might hit this, should add delta
372 std::cerr << "subcycleT > targetT, should not happen! (values: subcycleT " << subcycleT << ", subcycleDt " << subcycleDt << ", targetT " << targetT << ")" << std::endl;
373 }
374 break;
375 }
376
377 // Reassess subcycle dt
378 Real dtMaxGlobal = 0.0;
379 Real dtMaxLocal = fsgrid.parallel_reduction([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
380 phiprof::initializeTimer("compute-subcycle-dt-reduction-loop"), technical,
381 [](Real a, Real b) { return std::min<Real>(a, b); },
382 std::numeric_limits<Real>::max(),
383 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer, creal maximum) {
384 if (sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY ||
385 (sysBoundaryLayer == 1 && sysBoundaryFlag != sysboundarytype::NOT_SYSBOUNDARY)) {
386 return technical[stencil.ooo()].maxFsDt;
387 } else {
388 return maximum;
389 }
390 });
391
392 phiprof::Timer allreduceTimer{"MPI_Allreduce"};
393 fsgrid.Allreduce(&(dtMaxLocal), &(dtMaxGlobal), 1, MPI_Type<Real>(), MPI_MIN);
394 allreduceTimer.stop();
395
396 // reduce dt if it is too high
397 if (subcycleDt > dtMaxGlobal * P::fieldSolverMaxCFL) {
398 creal meanFieldsCFL = 0.5 * (P::fieldSolverMaxCFL + P::fieldSolverMinCFL);
399 subcycleDt = meanFieldsCFL * dtMaxGlobal;
400 if (myRank == MASTER_RANK) {
401 logFile << "(TIMESTEP) New field solver subcycle dt = " << subcycleDt << " computed on step " << P::tstep << " and substep " << subcycleCount << " at " << P::t << " s" << std::endl;
402 }
403 }
404
405 // Readjust the dt to hit targetT. Try to avoid having a very
406 // short delta step at the end, instead 2 more normal ones
407 if (subcycleT + 1.5 * subcycleDt > targetT) {
408 subcycleDt = targetT - subcycleT;
409 maxSubcycleCount = subcycleCount + 1; // 1 more steps
410 // check that subcyclDt has correct CFL, take 2 if not
411 if (subcycleDt > dtMaxGlobal * P::fieldSolverMaxCFL) {
412 subcycleDt = (targetT - subcycleT) / 2;
413 maxSubcycleCount = subcycleCount + 2;
414 }
415 }
416
417 subcyclingTimer.stop();
418 }
419
420 if (subcycles != subcycleCount && myRank == MASTER_RANK) {
421 logFile << "Effective field solver subcycles were " << subcycleCount << " instead of " << P::fieldSolverSubcycles << " on step " << P::tstep << std::endl;
422 }
423 }
424
425 calculateVolumeAveragedFieldsSimple(perb, e, dperb, vol, technical, fsgrid);
426 calculateBVOLDerivativesSimple(vol, technical, fsgrid);
428 fsgrid.updateGhostCells(vol);
429 calculateCurvatureSimple(vol, bgb, technical, fsgrid);
430 }
431 return true;
432}
dt
Definition Dispersion.m:39
SysBoundary contains the SysBoundaryConditions used in the simulation.
Definition sysboundary.h:54
#define MASTER_RANK
Definition common.h:67
@ RK_ORDER2_STEP1
Definition common.h:509
@ RK_ORDER1
Definition common.h:508
@ RK_ORDER2_STEP2
Definition common.h:510
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
T convert(const T &number)
Definition definitions.h:56
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const float creal
Definition definitions.h:42
void calculateBVOLDerivativesSimple(fsgrids::volspan vol, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
High-level derivative calculation wrapper function.
void calculateCurvatureSimple(fsgrids::volspan vol, fsgrids::constbgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
High-level curvature calculation wrapper function.
void calculateDerivativesSimple(fsgrids::perbspan perb, fsgrids::momentsspan moments, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const bool doMoments)
High-level derivative calculation wrapper function.
Definitions of the limiter functions used in the field solver.
int myRank
Definition gpu_base.cpp:48
Logger logFile
Definition main.cpp:25
void calculateUpwindedElectricFieldSimple(fsgrids::perbspan perb, fsgrids::perbspan perbdt2, fsgrids::efieldspan e, fsgrids::efieldspan edt2, fsgrids::ehallspan ehall, fsgrids::egradpespan egradpe, fsgrids::egradpespan egradpedt2, fsgrids::momentsspan moments, fsgrids::momentsspan momentsdt2, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::dmomentsspan dmomentsdt2, fsgrids::bgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, int32_t RKCase, const bool communicateEGradPeOrMomentsDerivatives)
High-level electric field computation function.
void calculateGradPeTermSimple(fsgrids::egradpespan egradpe, fsgrids::egradpespan egradpedt2, fsgrids::momentsspan moments, fsgrids::momentsspan momentsdt2, fsgrids::dmomentsspan dmoments, fsgrids::dmomentsspan dmomentsdt2, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, cint &RKCase)
void calculateHallTermSimple(fsgrids::perbspan perb, fsgrids::perbspan perbdt2, fsgrids::ehallspan ehall, fsgrids::momentsspan moments, fsgrids::momentsspan momentsdt2, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::dmomentsspan dmomentsdt2, fsgrids::bgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, int32_t RKCase, const bool communicateMomentsDerivatives)
High-level function computing the Hall term.
void propagateMagneticFieldSimple(fsgrids::perbspan perb, fsgrids::perbspan perbdt2, fsgrids::bgbspan bgb, fsgrids::efieldspan e, fsgrids::efieldspan edt2, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, creal &dt, cint &RKCase)
High-level magnetic field propagation function.
bool propagateFields(fsgrids::perbspan perb, fsgrids::perbspan perbdt2, fsgrids::efieldspan e, fsgrids::efieldspan edt2, fsgrids::ehallspan ehall, fsgrids::egradpespan egradpe, fsgrids::egradpespan egradpedt2, fsgrids::momentsspan moments, fsgrids::momentsspan momentsdt2, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::dmomentsspan dmomentsdt2, fsgrids::bgbspan bgb, fsgrids::volspan vol, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, creal &dt, cuint subcycles)
Top-level field propagation function.
Definition ldz_main.cpp:91
void calculateVolumeAveragedFieldsSimple(fsgrids::perbspan perb, fsgrids::efieldspan e, fsgrids::dperbspan dperb, fsgrids::volspan vol, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
Top-level field averaging function.
MPI_Datatype MPI_Type()
FieldTracingParameters fieldTracingParameters
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
Definition common.h:434
std::span< std::array< Real, fsgrids::moments::N_MOMENTS > > momentsspan
Definition common.h:446
std::span< std::array< Real, fsgrids::egradpe::N_EGRADPE > > egradpespan
Definition common.h:440
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
Definition common.h:448
std::span< technical > technicalspan
Definition common.h:452
std::span< std::array< Real, bgbfield::N_BGB > > bgbspan
Definition common.h:444
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
Definition common.h:442
std::span< std::array< Real, fsgrids::efield::N_EFIELD > > efieldspan
Definition common.h:436
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
Definition common.h:450
std::span< std::array< Real, fsgrids::ehall::N_EHALL > > ehallspan
Definition common.h:438
static uint ohmGradPeTerm
Definition parameters.h:144
static uint ohmHallTerm
Definition parameters.h:142
static uint fieldSolverSubcycles
Definition parameters.h:69
static Real fieldSolverMinCFL
Definition parameters.h:65
static Real t
Definition parameters.h:52
static bool computeCurvature
Definition parameters.h:268
static uint tstep
Definition parameters.h:73
static Real fieldSolverMaxCFL
Definition parameters.h:67