Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
inflow.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
27
28#include <cstdlib>
29#include <fstream>
30#include <iostream>
31
33#include "../object_wrapper.h"
35#include "../grid.h"
36#include "inflow.h"
37
38#ifdef DEBUG_VLASIATOR
39#define DEBUG_INFLOW
40#endif
41#ifdef DEBUG_SYSBOUNDARY
42#define DEBUG_INFLOW
43#endif
44
45namespace SBC {
48
50 // The array of bool describes which of the faces are to have inflow boundary
51 // conditions, in the order of x+, x-, y+, y-, z+, z-.
52 for(uint i=0; i<6; i++) {
53 facesToProcess[i] = false;
54 }
55
56 this->getParameters();
57
58 for (auto& it : faceList) {
59 if (it == "x+") {
60 facesToProcess[0] = true;
61 } else if (it == "x-") {
62 facesToProcess[1] = true;
63 } else if (it == "y+") {
64 facesToProcess[2] = true;
65 } else if (it == "y-") {
66 facesToProcess[3] = true;
67 } else if (it == "z+") {
68 facesToProcess[4] = true;
69 } else if (it == "z-") {
70 facesToProcess[5] = true;
71 }
72 }
73
74 for (unsigned int i = 0; i < speciesParams.size(); i++) {
76 }
77
79 tLastApply = t;
80 }
81
82 void Inflow::applyInitialState(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
85 fsgrids::bgbspan bgb, Project& project) {
86 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
87 setCellsFromTemplate(mpiGrid, popID);
88 }
89
90 if (P::isRestart) {
91 setBFromTemplate(mpiGrid, perb, bgb, technical, fsgrid, false);
92 } else {
93 setBFromTemplate(mpiGrid, perb, bgb, technical, fsgrid, true);
94 }
95 }
96
97 void Inflow::updateState(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
100 fsgrids::bgbspan bgb, creal t) {
101 if (t - tLastApply < tInterval) {
102 return;
103 } else {
104 tLastApply = t;
105 }
106 for (uint i = 0; i < 6; i++) {
107 if (facesToProcess[i]) {
109 }
110 }
111 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
112 setCellsFromTemplate(mpiGrid, popID);
113 }
114
115 setBFromTemplate(mpiGrid, perb, bgb, technical, fsgrid, false);
116
117 // Ensure up-to-date velocity block counts for all neighbours
118 for (uint popID=0; popID<getObjectWrapper().particleSpecies.size(); ++popID) {
120 }
121 }
122
126 const std::array<Real, 3>& gridSpacing,
127 const std::array<fsgrid::FsSize_t, 3>& globalCoordinates,
128 const fsgrid::FsStencil& stencil, cuint component) {
129 Real result = 0.0;
133 creal x = (convert<Real>(globalCoordinates[0]) + 0.5) * gridSpacing[0] + Parameters::xmin;
134 creal y = (convert<Real>(globalCoordinates[1]) + 0.5) * gridSpacing[1] + Parameters::ymin;
135 creal z = (convert<Real>(globalCoordinates[2]) + 0.5) * gridSpacing[2] + Parameters::zmin;
136
137 bool isThisCellOnAFace[6];
138 determineFace(&isThisCellOnAFace[0], x, y, z, dx, dy, dz, true);
139
140 for (uint i = 0; i < 6; i++) {
141 if (isThisCellOnAFace[i]) {
142 result = templateB[i][component];
143 break; // This effectively sets the precedence of faces through the order of faces.
144 }
145 }
146
147 // There are projects that have non-uniform and non-zero perturbed B, e.g. Magnetosphere with dipole type 4.
148 // We cannot jsut take the value from the templateCell, we also need a copy of the value from initialization.
149 // This value is stored in the BgBGrid at fsgrids::bgbfield::BGBXVDCORR,BGBYVDCORR,BGBZVDCORR
150 result += bgb[stencil.ooo()][fsgrids::bgbfield::BGBXVDCORR + component];
151 return result;
152 }
153
155 const fsgrid::FsStencil& stencil, cuint component) {
156 e[stencil.ooo()][fsgrids::efield::EX + component] = 0.0;
157 }
158
160 const fsgrid::FsStencil& stencil, cuint component) {
161 std::array<Real, fsgrids::ehall::N_EHALL>& cp = ehall[stencil.ooo()];
162 switch (component) {
163 case 0:
168 break;
169 case 1:
174 break;
175 case 2:
180 break;
181 default:
182 abort_mpi("Invalid component", 1);
183 }
184 }
185
187 fsgrids::egradpespan EGradPe, const fsgrid::FsStencil& stencil,
188 cuint component) {
189 EGradPe[stencil.ooo()][fsgrids::egradpe::EXGRADPE + component] = 0.0;
190 }
191
193 fsgrids::dmomentsspan dmoments,
194 const fsgrid::FsStencil& stencil, cuint RKCase, cuint component) {
195 this->setCellDerivativesToZero(dperb, dmoments, stencil, component);
196 }
197
199 const fsgrid::FsStencil& stencil, cuint component) {
200 this->setCellBVOLDerivativesToZero(vols, stencil, component);
201 }
202
203 void Inflow::vlasovBoundaryCondition(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
204 const CellID& cellID, const uint popID, const bool doCalcMomentsV) {
205 // This is a no-op because both template cell generation and block data copying takes place in
206 // updateState() (at pre-set intervals only)
207 }
208
209 void Inflow::setBFromTemplate(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
213 const bool resetSolved) {
214 const auto facesToProcess_local = this->facesToProcess;
215 std::array<bool, 3> periodic_local = this->periodic;
216 const auto templateB_local = this->templateB;
217 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
218 phiprof::initializeTimer("setBFromTemplate"), technical,
219 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
220 creal dx = P::dx_ini * pow(2, -technical[stencil.ooo()].refLevel);
221 creal dy = P::dy_ini * pow(2, -technical[stencil.ooo()].refLevel);
222 creal dz = P::dz_ini * pow(2, -technical[stencil.ooo()].refLevel);
223
224 std::array<bool, 6> isThisCellOnAFace = {{false}};
225 const std::array<Real, 3> coords = coordinates.getPhysicalCoords(stencil.i, stencil.j, stencil.k);
226 const std::array<Real, 3> gridSpacing = coordinates.physicalGridSpacing;
227
228 determineFaceNoClassMembers(isThisCellOnAFace.data(), coords[0] + 0.5 * gridSpacing[0], coords[1] + 0.5 * gridSpacing[1], coords[2] + 0.5 * gridSpacing[2], dx, dy, dz, periodic_local);
229
230 cuint bitfield = technical[stencil.ooo()].SOLVE;
231
232 for (uint iface = 0; iface < 6; iface++) {
233 if (facesToProcess_local[iface] && isThisCellOnAFace[iface]) {
234 // Reset all PerB components if requested, otherwise only unsolved components
235 if (resetSolved || (bitfield & compute::BX) != compute::BX) {
236 perb[stencil.ooo()][fsgrids::bfield::PERBX] = templateB_local[iface][0] + bgb[stencil.ooo()][fsgrids::bgbfield::BGBXVDCORR];
237 }
238 if (resetSolved || (bitfield & compute::BY) != compute::BY) {
239 perb[stencil.ooo()][fsgrids::bfield::PERBY] = templateB_local[iface][1] + bgb[stencil.ooo()][fsgrids::bgbfield::BGBYVDCORR];
240 }
241 if (resetSolved || (bitfield & compute::BZ) != compute::BZ) {
242 perb[stencil.ooo()][fsgrids::bfield::PERBZ] = templateB_local[iface][2] + bgb[stencil.ooo()][fsgrids::bgbfield::BGBZVDCORR];
243 }
244 break;
245 }
246 }
247 });
248 }
249
250 void Inflow::setCellsFromTemplate(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid, const uint popID) {
251 // Assign boundary flags to local DCCRG cells
252 const std::vector<CellID>& cells = getLocalCells();
253 #pragma omp parallel for schedule(dynamic, 1)
254 for (size_t c = 0; c < cells.size(); c++) {
255 SpatialCell* cell = mpiGrid[cells[c]];
256 if (cell->sysBoundaryFlag != this->getIndex()) {
257 continue;
258 }
260 creal dy = cell->parameters[CellParams::DY];
261 creal dz = cell->parameters[CellParams::DZ];
262 creal x = cell->parameters[CellParams::XCRD] + 0.5 * dx;
263 creal y = cell->parameters[CellParams::YCRD] + 0.5 * dy;
264 creal z = cell->parameters[CellParams::ZCRD] + 0.5 * dz;
265
266 bool isThisCellOnAFace[6];
267 determineFace(&isThisCellOnAFace[0], x, y, z, dx, dy, dz, true);
268
269 for (uint i = 0; i < 6; i++) {
270 if (facesToProcess[i] && isThisCellOnAFace[i]) {
271 copyCellData(&templateCells[i], cell, false, popID, true); // copy also vdf, _V
272 copyCellData(&templateCells[i], cell, true, popID, false); // don't copy vdf again but copy _R now
273 #ifdef USE_GPU
274 cell->setReservation(popID, templateCells[i].getReservation(popID));
275 #endif
276 break; // Effectively sets the precedence of faces through the order of faces.
277 }
278 }
279 }
280 // Verify current mesh and blocks
281 // if (!cell->checkMesh(popID)) {
282 // printf("ERROR in vmesh check: %s at %d\n",__FILE__,__LINE__);
283 // }
284 }
285
286 void Inflow::getFaces(bool* faces) {
287 for (uint i = 0; i < 6; i++) {
288 faces[i] = facesToProcess[i];
289 }
290 }
291
292 void Inflow::loadInputData(const uint popID) {
294
295 for (uint i = 0; i < 6; i++) {
296 if (facesToProcess[i])
297 sP.inputData[i] = loadFile(sP.files[i].c_str(), sP.nParams);
298 }
299 }
300
307 vector<std::vector<Real>> Inflow::loadFile(const char* fn, const unsigned int nParams) {
308 vector<std::vector<Real>> dataset(0, std::vector<Real>(nParams, 0));
309
310 ifstream fi;
311 fi.open(fn);
312
313 // Check that the file opened correctly
314 if (!fi.is_open()) {
315 cerr << "Could not open input file " << fn << "!" << endl;
316 MPI_Abort(MPI_COMM_WORLD, 1);
317 }
318
319 uint nlines = 0;
320 string line;
321 while (getline(fi, line)) {
322 vector<Real> vars(nParams, -7777);
323 // Skip the comments
324 if (line[0] == '#')
325 continue;
326 if (line.empty()) {
327 continue;
328 }
329 stringstream ss(line);
330
331 int i = 0;
332 Real num = 0;
333 while (ss >> num) {
334 if (i == int(nParams)) {
335 cerr << "Extra input values at line " << nlines + 1 << " in " << fn << endl;
336 MPI_Abort(MPI_COMM_WORLD, 1);
337 }
338 vars[i] = num;
339 i++;
340 }
341
342 for (vector<Real>::iterator v = vars.begin(); v != vars.end(); ++v) {
343 if (fabs(*v + 7777.) < numeric_limits<double>::epsilon()) {
344 cerr << "Missing input values at line " << nlines + 1 << " in " << fn << endl;
345 MPI_Abort(MPI_COMM_WORLD, 1);
346 }
347 }
348
349 dataset.push_back(vars);
350 nlines++;
351 }
352
353 if (nlines < 1) {
354 cerr << "Input file " << fn << " is empty!" << endl;
355 MPI_Abort(MPI_COMM_WORLD, 1);
356 } else if (nlines > 1) {
357 for (uint i = 1; i < nlines; ++i) {
358 if (dataset[i][0] < dataset[i - 1][0]) {
359 cerr << "Parameter data must be in ascending temporal order!" << endl;
360 MPI_Abort(MPI_COMM_WORLD, 1);
361 }
362 }
363 }
364
365 fi.close();
366
367 return dataset;
368 }
369
376 for (uint i = 0; i < 6; i++) {
377 if (facesToProcess[i]) {
379 }
380 }
381 }
382
390 void Inflow::interpolate(const int inputDataIndex, const uint popID, creal t, Real* outputData) {
391 const InflowSpeciesParameters& sP = speciesParams[popID];
392
393 // Find first data[0] value which is >= t
394 int i1 = 0, i2 = 0;
395 bool found = false;
396 Real s; // 0 <= s < 1
397
398 // Use the first value of data if interpolating for time before data starts
399 if (t < sP.inputData[inputDataIndex][0][0]) {
400 i1 = i2 = 0;
401 s = 0;
402 } else {
403 for (uint i = 0; i < sP.inputData[inputDataIndex].size(); i++) {
404 if (sP.inputData[inputDataIndex][i][0] >= t) {
405 found = true;
406 i2 = (int)i;
407 break;
408 }
409 }
410 if (found) {
411 // i2 is now "ceil(t)"
412 i1 = i2 - 1;
413 if (i1 < 0) {
414 i1 = i2 = 0;
415 s = 0.0;
416 } else {
417 // normal case, now both i1 and i2 are >= 0 and < nlines, and i1 = i2-1
418 s = (t - sP.inputData[inputDataIndex][i1][0]) /
419 (sP.inputData[inputDataIndex][i2][0] - sP.inputData[inputDataIndex][i1][0]);
420 }
421 } else {
422 i1 = i2 = sP.inputData[inputDataIndex].size() - 1;
423 s = 0.0;
424 }
425 }
426
427 creal s1 = 1 - s;
428
429 for (uint i = 0; i < sP.nParams - 1; i++) {
430 outputData[i] = s1 * sP.inputData[inputDataIndex][i1][i + 1] + s * sP.inputData[inputDataIndex][i2][i + 1];
431 }
432 }
433
434} // namespace SBC
for i
Definition Dispersion.m:24
dx
Definition Dispersion.m:38
Constants c
Definition Dispersion.m:45
spatial_cell::SpatialCell templateCells[6]
Definition inflow.h:106
void interpolate(const int inputDataIndex, const uint popID, creal t, Real *outputData)
Definition inflow.cpp:390
virtual void fieldSolverBoundaryCondElectricField(fsgrids::efieldspan e, const fsgrid::FsStencil &stencil, cuint component) override
Definition inflow.cpp:154
virtual void fieldSolverBoundaryCondHallElectricField(fsgrids::ehallspan ehall, const fsgrid::FsStencil &stencil, cuint component) override
Definition inflow.cpp:159
virtual void getFaces(bool *faces) override
Definition inflow.cpp:286
virtual void vlasovBoundaryCondition(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool doCalcMomentsV) override
Definition inflow.cpp:203
void generateTemplateCells(creal t)
Definition inflow.cpp:375
virtual void updateState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, creal t) override
Definition inflow.cpp:97
virtual ~Inflow()
Definition inflow.cpp:47
virtual void initSysBoundary(creal &t, Project &project) override
Definition inflow.cpp:49
Real tLastApply
Definition inflow.h:111
Real templateB[6][3]
Definition inflow.h:107
Real tInterval
Definition inflow.h:109
virtual void fieldSolverBoundaryCondDerivatives(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint RKCase, cuint component) override
Definition inflow.cpp:192
virtual void fieldSolverBoundaryCondBVOLDerivatives(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component) override
Definition inflow.cpp:198
std::vector< InflowSpeciesParameters > speciesParams
Definition inflow.h:114
void setCellsFromTemplate(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const uint popID)
Definition inflow.cpp:250
void loadInputData(const uint popID)
Definition inflow.cpp:292
std::vector< std::string > faceList
Definition inflow.h:113
virtual Real fieldSolverBoundaryCondMagneticField(fsgrids::perbspan b, fsgrids::constbgbspan bgb, fsgrids::consttechnicalspan technical, const std::array< Real, 3 > &gridSpacing, const std::array< fsgrid::FsSize_t, 3 > &globalCoordinates, const fsgrid::FsStencil &stencil, cuint component) override
Definition inflow.cpp:123
virtual void applyInitialState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, Project &project) override
Definition inflow.cpp:82
void setBFromTemplate(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const bool resetSolved)
Definition inflow.cpp:209
std::vector< std::vector< Real > > loadFile(const char *file, unsigned int nParams)
Definition inflow.cpp:307
virtual void fieldSolverBoundaryCondGradPeElectricField(fsgrids::egradpespan EGradPe, const fsgrid::FsStencil &stencil, cuint component) override
Definition inflow.cpp:186
std::array< bool, 6 > facesToProcess
static void setCellBVOLDerivativesToZero(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component)
void determineFace(bool *isThisCellOnAFace, const creal x, const creal y, const creal z, const creal dx, const creal dy, const creal dz, const bool excludeSlicesAndPeriodicDimensions=false) const
Function used to determine on which face(s) if any the cell at given coordinates is.
void copyCellData(const SpatialCell *from, SpatialCell *to, const bool copyMomentsOnly, const uint popID, const bool copy_V_moments)
static void setCellDerivativesToZero(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint component)
std::array< bool, 3 > periodic
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
void setReservation(const uint popID, const vmesh::LocalID reservationsize, bool force=false)
void abort_mpi(const std::string str, const int err_type)
Definition common.cpp:90
const std::vector< CellID > & getLocalCells()
Definition main.cpp:39
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
uint64_t CellID
Definition definitions.h:54
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 updateRemoteVelocityBlockLists(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const uint popID, const uint neighborhood)
Definition grid.cpp:919
ObjectWrapper & getObjectWrapper()
Definition main.cpp:33
void determineFaceNoClassMembers(bool *isThisCellOnAFace, creal x, creal y, creal z, creal dx, creal dy, creal dz, const std::array< bool, 3 > periodicity, const bool excludeSlicesAndPeriodicDimensions)
const uint BZ
Definition common.h:501
const uint BX
Definition common.h:499
const uint BY
Definition common.h:500
@ BGBZVDCORR
Definition common.h:383
@ BGBYVDCORR
Definition common.h:382
@ BGBXVDCORR
Definition common.h:381
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
Definition common.h:434
@ EXGRADPE
Definition common.h:305
std::span< const std::array< Real, bgbfield::N_BGB > > constbgbspan
Definition common.h:445
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
@ EZHALL_010_011
Definition common.h:295
@ EYHALL_101_111
Definition common.h:299
@ EYHALL_100_110
Definition common.h:292
@ EXHALL_010_110
Definition common.h:294
@ EZHALL_110_111
Definition common.h:296
@ EZHALL_000_001
Definition common.h:291
@ EYHALL_001_011
Definition common.h:298
@ EXHALL_001_101
Definition common.h:297
@ EYHALL_000_010
Definition common.h:290
@ EXHALL_000_100
Definition common.h:289
@ EXHALL_011_111
Definition common.h:300
@ EZHALL_100_101
Definition common.h:293
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< const technical > consttechnicalspan
Definition common.h:453
std::span< std::array< Real, fsgrids::efield::N_EFIELD > > efieldspan
Definition common.h:436
@ PERBY
Definition common.h:276
@ PERBZ
Definition common.h:277
@ PERBX
Definition common.h:275
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
std::vector< species::Species > particleSpecies
static Real dz_ini
Definition parameters.h:46
static Real dx_ini
Definition parameters.h:44
static Real ymin
Definition parameters.h:40
static Real xmin
Definition parameters.h:38
static bool isRestart
Definition parameters.h:176
static Real zmin
Definition parameters.h:42
static Real dy_ini
Definition parameters.h:45
std::string files[6]
Definition inflow.h:39
std::vector< std::vector< Real > > inputData[6]
Definition inflow.h:37