Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
gridGlue.cpp
Go to the documentation of this file.
1#include <dccrg.hpp>
2#include <dccrg_cartesian_geometry.hpp>
3#include "../grid.h"
5#include "../definitions.h"
6#include "../common.h"
7#include "gridGlue.hpp"
8
9
10// Datastructure for coupling
11std::map<int, std::set<CellID>> onDccrgMapRemoteProcessGlobal;
12std::map<int, std::set<CellID>> onFsgridMapRemoteProcessGlobal;
13std::map<CellID, std::vector<int64_t>> onFsgridMapCellsGlobal;
14
15/*
16Calculate the number of cells on the maximum refinement level overlapping the list of dccrg cells in cells.
17*/
18int getNumberOfCellsOnMaxRefLvl(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
19 const std::vector<CellID>& cells) {
20
21 int nCells = 0;
22 auto maxRefLvl = mpiGrid.mapping.get_maximum_refinement_level();
23
24 for (auto cellid : cells) {
25 auto refLvl = mpiGrid.get_refinement_level(cellid);
26 nCells += pow(pow(2, maxRefLvl - refLvl), 3);
27 }
28
29 return nCells;
30}
31
32/*
33Copy moments from simulation domain to outflow boundaries on fsgrid
34*/
35void copyMomentsToOutflow(fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>>& moments,
36 fsgrids::technicalspan technical,
38
39 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
40 phiprof::initializeTimer("copyMomentsToOutflow loop"), technical,
41 [&](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
42 // Copying only needs to be done for L1/L2 outflow cells
43 if (technical[stencil.ooo()].sysBoundaryFlag != sysboundarytype::OUTFLOW || technical[stencil.ooo()].sysBoundaryLayer > 2) {
44 return;
45 }
46
47 int distance = numeric_limits<int>::max();
48 array<int,3> closestCellOffset = {numeric_limits<int>::max(), numeric_limits<int>::max(), numeric_limits<int>::max()};
49
50 for (int kk=-2; kk<3; kk++) {
51 for (int jj=-2; jj<3; jj++) {
52 for (int ii=-2; ii<3 ; ii++) {
53 if( stencil.cellExists(ii,jj,kk) // skip invalid cells returning NULL
54 && technical[stencil.indexFromOffset(ii,jj,kk)].sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY // Copy only from sim domain
55 ) {
56 if(distance > ii*ii + jj*jj + kk*kk) {
57 distance = ii*ii + jj*jj + kk*kk;
58 closestCellOffset = {ii, jj, kk};
59 }
60 }
61 }
62 }
63 }
64
65 if (closestCellOffset[0] == numeric_limits<int>::max()) {
66 abort_mpi("No closest cell found!", 1);
67 }
68
69 // Set outflow cell to closest in-domain cell values
70 for (int e = 0; e < fsgrids::moments::N_MOMENTS; ++e) {
71 moments[stencil.ooo()][e] = moments[stencil.indexFromOffset(closestCellOffset[0], closestCellOffset[1], closestCellOffset[2])][fsgrids::moments::RHOM+e];
72 }
73 });
74}
75
76/*
77Filter moments after feeding them to FsGrid to alleviate the staircase effect caused in AMR runs.
78This is using a 3D, 5-point stencil triangle kernel.
79*/
80void filterMoments(fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>>& moments,
82
83 // Kernel Characteristics
84 constexpr int kernelOffset = 2; // offset of 5 pointstencil 3D kernel => (floor(stencilWidth/2);)
85 constexpr Real inverseKernelSum = 1.0 / 729.0; // the inverse of the total kernel's sum
86 constexpr Real kernel[5][5][5] = {
87 {{1 * inverseKernelSum, 2 * inverseKernelSum, 3 * inverseKernelSum, 2 * inverseKernelSum, 1 * inverseKernelSum},
88 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
89 {3 * inverseKernelSum, 6 * inverseKernelSum, 9 * inverseKernelSum, 6 * inverseKernelSum, 3 * inverseKernelSum},
90 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
91 {1 * inverseKernelSum, 2 * inverseKernelSum, 3 * inverseKernelSum, 2 * inverseKernelSum, 1 * inverseKernelSum}},
92
93 {{2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
94 {4 * inverseKernelSum, 8 * inverseKernelSum, 12 * inverseKernelSum, 8 * inverseKernelSum, 4 * inverseKernelSum},
95 {6 * inverseKernelSum, 12 * inverseKernelSum, 18 * inverseKernelSum, 12 * inverseKernelSum, 6 * inverseKernelSum},
96 {4 * inverseKernelSum, 8 * inverseKernelSum, 12 * inverseKernelSum, 8 * inverseKernelSum, 4 * inverseKernelSum},
97 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum}},
98
99 {{3 * inverseKernelSum, 6 * inverseKernelSum, 9 * inverseKernelSum, 6 * inverseKernelSum, 3 * inverseKernelSum},
100 {6 * inverseKernelSum, 12 * inverseKernelSum, 18 * inverseKernelSum, 12 * inverseKernelSum, 6 * inverseKernelSum},
101 {9 * inverseKernelSum, 18 * inverseKernelSum, 27 * inverseKernelSum, 18 * inverseKernelSum, 9 * inverseKernelSum},
102 {6 * inverseKernelSum, 12 * inverseKernelSum, 18 * inverseKernelSum, 12 * inverseKernelSum, 6 * inverseKernelSum},
103 {3 * inverseKernelSum, 6 * inverseKernelSum, 9 * inverseKernelSum, 6 * inverseKernelSum, 3 * inverseKernelSum}},
104
105 {{2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
106 {4 * inverseKernelSum, 8 * inverseKernelSum, 12 * inverseKernelSum, 8 * inverseKernelSum, 4 * inverseKernelSum},
107 {6 * inverseKernelSum, 12 * inverseKernelSum, 18 * inverseKernelSum, 12 * inverseKernelSum, 6 * inverseKernelSum},
108 {4 * inverseKernelSum, 8 * inverseKernelSum, 12 * inverseKernelSum, 8 * inverseKernelSum, 4 * inverseKernelSum},
109 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum}},
110
111 {{1 * inverseKernelSum, 2 * inverseKernelSum, 3 * inverseKernelSum, 2 * inverseKernelSum, 1 * inverseKernelSum},
112 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
113 {3 * inverseKernelSum, 6 * inverseKernelSum, 9 * inverseKernelSum, 6 * inverseKernelSum, 3 * inverseKernelSum},
114 {2 * inverseKernelSum, 4 * inverseKernelSum, 6 * inverseKernelSum, 4 * inverseKernelSum, 2 * inverseKernelSum},
115 {1 * inverseKernelSum, 2 * inverseKernelSum, 3 * inverseKernelSum, 2 * inverseKernelSum, 1 * inverseKernelSum}}};
116
117 // Create a copy of moments data for filtering
118 fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>> blurred(moments.size());
119
120 // Update momentsGrid Ghost Cells
121 fsgrid.updateGhostCells(moments.view());
122
123 // Filtering Loop
124 for (auto blurPass = 0; blurPass < Parameters::maxFilteringPasses; blurPass++) {
125 // Blurring Pass
126 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
127 phiprof::initializeTimer("Filtering loop"), technical,
128 [&](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
129 const auto refLevel = technical[stencil.ooo()].refLevel;
130 auto& blurCell = blurred[stencil.ooo()];
131
132 // Skip pass, set blurCell value equal to original
133 if (blurPass >= P::numPasses.at(refLevel) || sysBoundaryFlag != sysboundarytype::NOT_SYSBOUNDARY) {
134 blurCell = moments[stencil.ooo()];
135 // this was a continue before moving to parallel_for, now the rest of the body of the loop is in the else below.
136 } else {
137 // Set Cell to zero before passing filter
138 blurCell.fill(0.0);
139
140 // Perform the blur
141 for (int c = -kernelOffset; c <= kernelOffset; c++) {
142 for (int b = -kernelOffset; b <= kernelOffset; b++) {
143 for (int a = -kernelOffset; a <= kernelOffset; a++) {
144 const auto& cell = moments[stencil.indexFromOffset(a,b,c)];
145 #pragma omp simd
146 for (int e = 0; e < fsgrids::moments::N_MOMENTS; ++e) {
147 blurCell[e] += cell[e] * kernel[kernelOffset + a][kernelOffset + b][kernelOffset + c];
148 }
149 }
150 }
151 } // inner filtering loop
152 } // else
153 });
154
155 using std::swap;
156 swap(moments, blurred);
157 fsgrid.updateGhostCells(moments.view());
158
159 // If outflow boundaries exist, filtered moments must be recopied there
160 copyMomentsToOutflow(moments, technical, fsgrid);
161 fsgrid.updateGhostCells(moments.view());
162 }
163}
164
165void feedMomentsIntoFsGrid(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
166 const std::vector<CellID>& cells,
167 fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>>& moments,
168 fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, bool dt2 /*=false*/) {
169
170 int ii;
171 // sorted list of dccrg cells. cells is typicall already sorted, but just to make sure....
172 std::vector<CellID> dccrgCells = cells;
173 std::sort(dccrgCells.begin(), dccrgCells.end());
174
175 // map receive process => receive buffers
176 std::map<int, std::vector<Real>> receivedData;
177
178 // send buffers to each process
179 std::map<int, std::vector<Real>> sendData;
180
181 // list of requests
182 std::vector<MPI_Request> sendRequests;
183 std::vector<MPI_Request> receiveRequests;
184
185 // Post receives
186 receiveRequests.resize(onFsgridMapRemoteProcessGlobal.size());
187 ii = 0;
188 for (auto const& receives : onFsgridMapRemoteProcessGlobal) {
189 int process = receives.first;
190 int count = receives.second.size();
191 receivedData[process].resize(count * fsgrids::moments::N_MOMENTS);
192 MPI_Irecv(receivedData[process].data(), count * fsgrids::moments::N_MOMENTS * sizeof(Real),
193 MPI_BYTE, process, 1, MPI_COMM_WORLD, &(receiveRequests[ii++]));
194 }
195
196 // Launch sends
197 ii = 0;
198 sendRequests.resize(onDccrgMapRemoteProcessGlobal.size());
199 for (auto const& snd : onDccrgMapRemoteProcessGlobal) {
200 int targetProc = snd.first;
201 auto& sendBuffer = sendData[targetProc];
202 for (CellID sendCell : snd.second) {
203 // Collect data to send for this dccrg cell
204 auto cellParams = mpiGrid[sendCell]->get_cell_parameters();
205 if (!dt2) {
206 sendBuffer.push_back(cellParams[CellParams::RHOM]);
207 sendBuffer.push_back(cellParams[CellParams::RHOQ]);
208 sendBuffer.push_back(cellParams[CellParams::VX]);
209 sendBuffer.push_back(cellParams[CellParams::VY]);
210 sendBuffer.push_back(cellParams[CellParams::VZ]);
211 sendBuffer.push_back(cellParams[CellParams::P_11]);
212 sendBuffer.push_back(cellParams[CellParams::P_22]);
213 sendBuffer.push_back(cellParams[CellParams::P_33]);
214 } else {
215 sendBuffer.push_back(cellParams[CellParams::RHOM_DT2]);
216 sendBuffer.push_back(cellParams[CellParams::RHOQ_DT2]);
217 sendBuffer.push_back(cellParams[CellParams::VX_DT2]);
218 sendBuffer.push_back(cellParams[CellParams::VY_DT2]);
219 sendBuffer.push_back(cellParams[CellParams::VZ_DT2]);
220 sendBuffer.push_back(cellParams[CellParams::P_11_DT2]);
221 sendBuffer.push_back(cellParams[CellParams::P_22_DT2]);
222 sendBuffer.push_back(cellParams[CellParams::P_33_DT2]);
223 }
224 }
225 MPI_Isend(sendBuffer.data(), sendBuffer.size() * sizeof(Real),
226 MPI_BYTE, targetProc, 1, MPI_COMM_WORLD, &(sendRequests[ii]));
227 ii++;
228 }
229
230 MPI_Waitall(receiveRequests.size(), receiveRequests.data(), MPI_STATUSES_IGNORE);
231
232 for (auto const& receives : onFsgridMapRemoteProcessGlobal) {
233 int process = receives.first; // data received from this process
234 Real* receiveBuffer = receivedData[process].data(); // data received from process
235 for (auto const& cell : receives.second) { // loop over cellids (dccrg) for receive
236 // this part heavily relies on both sender and receiver having cellids sorted!
237 for (auto lid : onFsgridMapCellsGlobal[cell]) {
238 auto& moment = moments[static_cast<size_t>(lid)];
239 for (int l = 0; l < fsgrids::moments::N_MOMENTS; l++) {
240 moment[l] = receiveBuffer[l];
241 }
242 }
243
244 receiveBuffer += fsgrids::moments::N_MOMENTS;
245 }
246 }
247
248 MPI_Waitall(sendRequests.size(), sendRequests.data(), MPI_STATUSES_IGNORE);
249
250 // Filter Moments if this is a 3D AMR run.
251 if (P::amrMaxSpatialRefLevel > 0) {
252 phiprof::Timer filteringTimer{"AMR Filtering-Triangle-3D"};
253 filterMoments(moments, technical, fsgrid);
254 }
255}
256
262 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
263 const std::vector<CellID>& cells) {
264 // TODO: solver only needs bgb + PERB, we could combine them
265 const auto& gridSpacing = fsgrid.getGridSpacing();
266
267 struct Average {
269 int cells;
270 Average() {
271 cells = 0;
272 for (int i = 0; i < N_FIELDSTOCOMMUNICATE; i++) {
273 sums[i] = 0;
274 }
275 }
276 Average operator+=(const Average& rhs) {
277 this->cells += rhs.cells;
278 for (int i = 0; i < N_FIELDSTOCOMMUNICATE; i++) {
279 this->sums[i] += rhs.sums[i];
280 }
281 return *this;
282 }
283 };
284
285 int ii;
286 // sorted list of dccrg cells. cells is typicall already sorted, but just to make sure....
287 std::vector<CellID> dccrgCells = cells;
288 std::sort(dccrgCells.begin(), dccrgCells.end());
289
290 // map receive process => receive buffers
291 std::map<int, std::vector<Average>> receivedData;
292
293 // send buffers to each process
294 std::map<int, std::vector<Average>> sendData;
295
296 // map where we finally aggregate result for each local dccrg cell
297 std::map<CellID, Average> aggregatedResult;
298
299 // list of requests
300 std::vector<MPI_Request> sendRequests;
301 std::vector<MPI_Request> receiveRequests;
302
303 // post receives
304 ii = 0;
305 receiveRequests.resize(onDccrgMapRemoteProcessGlobal.size());
306 for (auto const& rcv : onDccrgMapRemoteProcessGlobal) {
307 int remoteRank = rcv.first;
308 int count = rcv.second.size();
309 auto& receiveBuffer = receivedData[remoteRank];
310
311 receiveBuffer.resize(count);
312 MPI_Irecv(receiveBuffer.data(), count * sizeof(Average),
313 MPI_BYTE, remoteRank, 1, MPI_COMM_WORLD, &(receiveRequests[ii++]));
314 }
315
316 // compute average and weight for each field that we want to send to dccrg grid
317 for (auto const& snd : onFsgridMapRemoteProcessGlobal) {
318 int remoteRank = snd.first;
319 int count = snd.second.size();
320 auto& sendBuffer = sendData[remoteRank];
321 sendBuffer.resize(count);
322
323 ii = 0;
324 for (auto const dccrgCell : snd.second) {
325 // loop over dccrg cells to which we shall send data for this remoteRank
326 auto const& fsgridCells = onFsgridMapCellsGlobal[dccrgCell];
327 for (auto const fsgridCell : fsgridCells) {
328 // loop over fsgrid cells for which we compute the average that is sent to dccrgCell on rank remoteRank
329 if (technical[fsgridCell].sysBoundaryFlag == sysboundarytype::OUTER_BOUNDARY_PADDING) {
330 // We skip boundary padding cells on the outer boundaries here,
331 // because their fields anyway don't contribute anything
332 // meaningful (as there are never properly updated).
333 //
334 // Note we do *NOT* skip DO_NOT_COMPUTE cells, because we need
335 // the bg vol fields to contribute to the innermost simulation
336 // cell's DCCRG volume averages.
337 continue;
338 }
339 const std::array<Real, fsgrids::volfields::N_VOL>& volcell = volumefields[fsgridCell];
340 const std::array<Real, fsgrids::bgbfield::N_BGB>& bgcell = bgb[fsgridCell];
341 const std::array<Real, fsgrids::egradpe::N_EGRADPE>& egradpecell = egradpe[fsgridCell];
342 const std::array<Real, fsgrids::dmoments::N_DMOMENTS>& dMomentscell = dmoments[fsgridCell];
343
344 // TODO consider pruning these and communicating only when required
345 sendBuffer[ii].sums[FieldsToCommunicate::PERBXVOL] += volcell[fsgrids::volfields::PERBXVOL];
346 sendBuffer[ii].sums[FieldsToCommunicate::PERBYVOL] += volcell[fsgrids::volfields::PERBYVOL];
347 sendBuffer[ii].sums[FieldsToCommunicate::PERBZVOL] += volcell[fsgrids::volfields::PERBZVOL];
348 sendBuffer[ii].sums[FieldsToCommunicate::dPERBXVOLdx] += volcell[fsgrids::volfields::dPERBXVOLdx] / gridSpacing[0];
349 sendBuffer[ii].sums[FieldsToCommunicate::dPERBXVOLdy] += volcell[fsgrids::volfields::dPERBXVOLdy] / gridSpacing[1];
350 sendBuffer[ii].sums[FieldsToCommunicate::dPERBXVOLdz] += volcell[fsgrids::volfields::dPERBXVOLdz] / gridSpacing[2];
351 sendBuffer[ii].sums[FieldsToCommunicate::dPERBYVOLdx] += volcell[fsgrids::volfields::dPERBYVOLdx] / gridSpacing[0];
352 sendBuffer[ii].sums[FieldsToCommunicate::dPERBYVOLdy] += volcell[fsgrids::volfields::dPERBYVOLdy] / gridSpacing[1];
353 sendBuffer[ii].sums[FieldsToCommunicate::dPERBYVOLdz] += volcell[fsgrids::volfields::dPERBYVOLdz] / gridSpacing[2];
354 sendBuffer[ii].sums[FieldsToCommunicate::dPERBZVOLdx] += volcell[fsgrids::volfields::dPERBZVOLdx] / gridSpacing[0];
355 sendBuffer[ii].sums[FieldsToCommunicate::dPERBZVOLdy] += volcell[fsgrids::volfields::dPERBZVOLdy] / gridSpacing[1];
356 sendBuffer[ii].sums[FieldsToCommunicate::dPERBZVOLdz] += volcell[fsgrids::volfields::dPERBZVOLdz] / gridSpacing[2];
357 sendBuffer[ii].sums[FieldsToCommunicate::dVxdx] += dMomentscell[fsgrids::dmoments::dVxdx] / gridSpacing[0];
358 sendBuffer[ii].sums[FieldsToCommunicate::dVxdy] += dMomentscell[fsgrids::dmoments::dVxdy] / gridSpacing[1];
359 sendBuffer[ii].sums[FieldsToCommunicate::dVxdz] += dMomentscell[fsgrids::dmoments::dVxdz] / gridSpacing[2];
360 sendBuffer[ii].sums[FieldsToCommunicate::dVydx] += dMomentscell[fsgrids::dmoments::dVydx] / gridSpacing[0];
361 sendBuffer[ii].sums[FieldsToCommunicate::dVydy] += dMomentscell[fsgrids::dmoments::dVydy] / gridSpacing[1];
362 sendBuffer[ii].sums[FieldsToCommunicate::dVydz] += dMomentscell[fsgrids::dmoments::dVydz] / gridSpacing[2];
363 sendBuffer[ii].sums[FieldsToCommunicate::dVzdx] += dMomentscell[fsgrids::dmoments::dVzdx] / gridSpacing[0];
364 sendBuffer[ii].sums[FieldsToCommunicate::dVzdy] += dMomentscell[fsgrids::dmoments::dVzdy] / gridSpacing[1];
365 sendBuffer[ii].sums[FieldsToCommunicate::dVzdz] += dMomentscell[fsgrids::dmoments::dVzdz] / gridSpacing[2];
366 sendBuffer[ii].sums[FieldsToCommunicate::BGBXVOL] += bgcell[fsgrids::bgbfield::BGBXVOL];
367 sendBuffer[ii].sums[FieldsToCommunicate::BGBYVOL] += bgcell[fsgrids::bgbfield::BGBYVOL];
368 sendBuffer[ii].sums[FieldsToCommunicate::BGBZVOL] += bgcell[fsgrids::bgbfield::BGBZVOL];
369 sendBuffer[ii].sums[FieldsToCommunicate::EXGRADPE] += egradpecell[fsgrids::egradpe::EXGRADPE];
370 sendBuffer[ii].sums[FieldsToCommunicate::EYGRADPE] += egradpecell[fsgrids::egradpe::EYGRADPE];
371 sendBuffer[ii].sums[FieldsToCommunicate::EZGRADPE] += egradpecell[fsgrids::egradpe::EZGRADPE];
372 sendBuffer[ii].sums[FieldsToCommunicate::EXVOL] += volcell[fsgrids::volfields::EXVOL];
373 sendBuffer[ii].sums[FieldsToCommunicate::EYVOL] += volcell[fsgrids::volfields::EYVOL];
374 sendBuffer[ii].sums[FieldsToCommunicate::EZVOL] += volcell[fsgrids::volfields::EZVOL];
378 sendBuffer[ii].cells++;
379 }
380 ii++;
381 }
382 }
383
384 // post sends
385 sendRequests.resize(onFsgridMapRemoteProcessGlobal.size());
386 ii = 0;
387 for (auto const& sends : onFsgridMapRemoteProcessGlobal) {
388 int remoteRank = sends.first;
389 int count = sends.second.size();
390 MPI_Isend(sendData[remoteRank].data(), count * sizeof(Average),
391 MPI_BYTE, remoteRank, 1, MPI_COMM_WORLD, &(sendRequests[ii++]));
392 }
393
394 MPI_Waitall(receiveRequests.size(), receiveRequests.data(), MPI_STATUSES_IGNORE);
395
396 // Aggregate receives, compute the weighted average of these
397 ii = 0;
398 for (auto const& rcv : onDccrgMapRemoteProcessGlobal) {
399 int remoteRank = rcv.first;
400 std::vector<Average>& receiveBuffer = receivedData[remoteRank];
401 ii = 0;
402 for (CellID dccrgCell : rcv.second) {
403 // aggregate result. Average strct has operator += and a constructor
404 aggregatedResult[dccrgCell] += receiveBuffer[ii++];
405 }
406 }
407
408 // Store data in dccrg
409 for (auto const& cellAggregate : aggregatedResult) {
410 auto cellParams = mpiGrid[cellAggregate.first]->get_cell_parameters();
411 if (cellAggregate.second.cells > 0) {
412 cellParams[CellParams::PERBXVOL] = cellAggregate.second.sums[FieldsToCommunicate::PERBXVOL] / cellAggregate.second.cells;
413 cellParams[CellParams::PERBYVOL] = cellAggregate.second.sums[FieldsToCommunicate::PERBYVOL] / cellAggregate.second.cells;
414 cellParams[CellParams::PERBZVOL] = cellAggregate.second.sums[FieldsToCommunicate::PERBZVOL] / cellAggregate.second.cells;
415 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdx] = cellAggregate.second.sums[FieldsToCommunicate::dPERBXVOLdx] / cellAggregate.second.cells;
416 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdy] = cellAggregate.second.sums[FieldsToCommunicate::dPERBXVOLdy] / cellAggregate.second.cells;
417 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdz] = cellAggregate.second.sums[FieldsToCommunicate::dPERBXVOLdz] / cellAggregate.second.cells;
418 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdx] = cellAggregate.second.sums[FieldsToCommunicate::dPERBYVOLdx] / cellAggregate.second.cells;
419 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdy] = cellAggregate.second.sums[FieldsToCommunicate::dPERBYVOLdy] / cellAggregate.second.cells;
420 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdz] = cellAggregate.second.sums[FieldsToCommunicate::dPERBYVOLdz] / cellAggregate.second.cells;
421 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdx] = cellAggregate.second.sums[FieldsToCommunicate::dPERBZVOLdx] / cellAggregate.second.cells;
422 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdy] = cellAggregate.second.sums[FieldsToCommunicate::dPERBZVOLdy] / cellAggregate.second.cells;
423 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdz] = cellAggregate.second.sums[FieldsToCommunicate::dPERBZVOLdz] / cellAggregate.second.cells;
424 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdx] = cellAggregate.second.sums[FieldsToCommunicate::dVxdx] / cellAggregate.second.cells;
425 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdy] = cellAggregate.second.sums[FieldsToCommunicate::dVxdy] / cellAggregate.second.cells;
426 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdz] = cellAggregate.second.sums[FieldsToCommunicate::dVxdz] / cellAggregate.second.cells;
427 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydx] = cellAggregate.second.sums[FieldsToCommunicate::dVydx] / cellAggregate.second.cells;
428 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydy] = cellAggregate.second.sums[FieldsToCommunicate::dVydy] / cellAggregate.second.cells;
429 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydz] = cellAggregate.second.sums[FieldsToCommunicate::dVydz] / cellAggregate.second.cells;
430 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdx] = cellAggregate.second.sums[FieldsToCommunicate::dVzdx] / cellAggregate.second.cells;
431 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdy] = cellAggregate.second.sums[FieldsToCommunicate::dVzdy] / cellAggregate.second.cells;
432 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdz] = cellAggregate.second.sums[FieldsToCommunicate::dVzdz] / cellAggregate.second.cells;
433 cellParams[CellParams::BGBXVOL] = cellAggregate.second.sums[FieldsToCommunicate::BGBXVOL] / cellAggregate.second.cells;
434 cellParams[CellParams::BGBYVOL] = cellAggregate.second.sums[FieldsToCommunicate::BGBYVOL] / cellAggregate.second.cells;
435 cellParams[CellParams::BGBZVOL] = cellAggregate.second.sums[FieldsToCommunicate::BGBZVOL] / cellAggregate.second.cells;
436 cellParams[CellParams::EXGRADPE] = cellAggregate.second.sums[FieldsToCommunicate::EXGRADPE] / cellAggregate.second.cells;
437 cellParams[CellParams::EYGRADPE] = cellAggregate.second.sums[FieldsToCommunicate::EYGRADPE] / cellAggregate.second.cells;
438 cellParams[CellParams::EZGRADPE] = cellAggregate.second.sums[FieldsToCommunicate::EZGRADPE] / cellAggregate.second.cells;
439 cellParams[CellParams::EXVOL] = cellAggregate.second.sums[FieldsToCommunicate::EXVOL] / cellAggregate.second.cells;
440 cellParams[CellParams::EYVOL] = cellAggregate.second.sums[FieldsToCommunicate::EYVOL] / cellAggregate.second.cells;
441 cellParams[CellParams::EZVOL] = cellAggregate.second.sums[FieldsToCommunicate::EZVOL] / cellAggregate.second.cells;
442 cellParams[CellParams::CURVATUREX] = cellAggregate.second.sums[FieldsToCommunicate::CURVATUREX] / cellAggregate.second.cells;
443 cellParams[CellParams::CURVATUREY] = cellAggregate.second.sums[FieldsToCommunicate::CURVATUREY] / cellAggregate.second.cells;
444 cellParams[CellParams::CURVATUREZ] = cellAggregate.second.sums[FieldsToCommunicate::CURVATUREZ] / cellAggregate.second.cells;
445 } else {
446 // This could happpen if all fsgrid cells are do not compute
447 cellParams[CellParams::PERBXVOL] = 0;
448 cellParams[CellParams::PERBYVOL] = 0;
449 cellParams[CellParams::PERBZVOL] = 0;
450 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdx] = 0;
451 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdy] = 0;
452 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBXVOLdz] = 0;
453 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdx] = 0;
454 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdy] = 0;
455 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBYVOLdz] = 0;
456 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdx] = 0;
457 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdy] = 0;
458 mpiGrid[cellAggregate.first]->derivativesBVOL[bvolderivatives::dPERBZVOLdz] = 0;
459 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdx] = 0;
460 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdy] = 0;
461 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVxdz] = 0;
462 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydx] = 0;
463 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydy] = 0;
464 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVydz] = 0;
465 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdx] = 0;
466 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdy] = 0;
467 mpiGrid[cellAggregate.first]->derivativesV[vderivatives::dVzdz] = 0;
468 cellParams[CellParams::BGBXVOL] = 0;
469 cellParams[CellParams::BGBYVOL] = 0;
470 cellParams[CellParams::BGBZVOL] = 0;
471 cellParams[CellParams::EXGRADPE] = 0;
472 cellParams[CellParams::EYGRADPE] = 0;
473 cellParams[CellParams::EZGRADPE] = 0;
474 cellParams[CellParams::EXVOL] = 0;
475 cellParams[CellParams::EYVOL] = 0;
476 cellParams[CellParams::EZVOL] = 0;
477 cellParams[CellParams::CURVATUREX] = 0;
478 cellParams[CellParams::CURVATUREY] = 0;
479 cellParams[CellParams::CURVATUREZ] = 0;
480 }
481 }
482
483 MPI_Waitall(sendRequests.size(), sendRequests.data(), MPI_STATUSES_IGNORE);
484}
485
486/*
487Map from dccrg cell id to fsgrid global cell ids when they aren't identical (ie. when dccrg has refinement).
488*/
489
490std::vector<CellID> mapDccrgIdToFsGridGlobalID(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
491 CellID dccrgID) {
492 const auto maxRefLvl = mpiGrid.get_maximum_refinement_level();
493 const auto refLvl = mpiGrid.get_refinement_level(dccrgID);
494 const auto cellLength = pow(2, maxRefLvl - refLvl);
495 const auto topLeftIndices = mpiGrid.mapping.get_indices(dccrgID);
496 std::array<int, 3> fsgridDims;
497
498 fsgridDims[0] = P::xcells_ini * pow(2, mpiGrid.get_maximum_refinement_level());
499 fsgridDims[1] = P::ycells_ini * pow(2, mpiGrid.get_maximum_refinement_level());
500 fsgridDims[2] = P::zcells_ini * pow(2, mpiGrid.get_maximum_refinement_level());
501
502 std::vector<CellID> fsgridIDs(cellLength * cellLength * cellLength);
503 for (uint k = 0; k < cellLength; ++k) {
504 for (uint j = 0; j < cellLength; ++j) {
505 for (uint i = 0; i < cellLength; ++i) {
506 const std::array<uint64_t, 3> indices = {
507 {topLeftIndices[0] + i, topLeftIndices[1] + j, topLeftIndices[2] + k}};
508 fsgridIDs[k * cellLength * cellLength + j * cellLength + i] =
509 indices[0] + indices[1] * fsgridDims[0] + indices[2] * fsgridDims[1] * fsgridDims[0];
510 }
511 }
512 }
513 return fsgridIDs;
514}
515
516void feedBoundaryIntoFsGrid(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
517 const std::vector<CellID>& cells,
519 int ii;
520 // sorted list of dccrg cells. cells is typicall already sorted, but just to make sure....
521 std::vector<CellID> dccrgCells = cells;
522 std::sort(dccrgCells.begin(), dccrgCells.end());
523
524 // map receive process => receive buffers
525 std::map<int, std::vector<int>> receivedData;
526
527 // send buffers to each process
528 std::map<int, std::vector<int>> sendData;
529
530 // list of requests
531 std::vector<MPI_Request> sendRequests;
532 std::vector<MPI_Request> receiveRequests;
533
534 // Post receives
535 receiveRequests.resize(onFsgridMapRemoteProcessGlobal.size());
536 ii = 0;
537 for (auto const& receives : onFsgridMapRemoteProcessGlobal) {
538 int process = receives.first;
539 int count = receives.second.size();
540 receivedData[process].resize(count);
541 MPI_Irecv(receivedData[process].data(), count * sizeof(int),
542 MPI_BYTE, process, 1, MPI_COMM_WORLD, &(receiveRequests[ii++]));
543 }
544
545 // Launch sends
546 ii = 0;
547 sendRequests.resize(onDccrgMapRemoteProcessGlobal.size());
548 for (auto const& snd : onDccrgMapRemoteProcessGlobal) {
549 int targetProc = snd.first;
550 auto& sendBuffer = sendData[targetProc];
551 for (CellID sendCell : snd.second) {
552 // Collect data to send for this dccrg cell
553 sendBuffer.push_back(mpiGrid[sendCell]->sysBoundaryFlag);
554 }
555 MPI_Isend(sendBuffer.data(), sendBuffer.size() * sizeof(int),
556 MPI_BYTE, targetProc, 1, MPI_COMM_WORLD, &(sendRequests[ii]));
557 ii++;
558 }
559
560 MPI_Waitall(receiveRequests.size(), receiveRequests.data(), MPI_STATUSES_IGNORE);
561
562 for (auto const& receives : onFsgridMapRemoteProcessGlobal) {
563 int process = receives.first; // data received from this process
564 int* receiveBuffer = receivedData[process].data(); // data received from process
565 for (auto const& cell : receives.second) { // loop over cellids (dccrg) for receive
566 // this part heavily relies on both sender and receiver having cellids sorted!
567 for (auto lid : onFsgridMapCellsGlobal[cell]) {
568 // Now save the values to face-averages
569 technical[lid].sysBoundaryFlag = receiveBuffer[0];
570 }
571
572 receiveBuffer++;
573 }
574 }
575
576 MPI_Waitall(sendRequests.size(), sendRequests.data(), MPI_STATUSES_IGNORE);
577}
for i
Definition Dispersion.m:24
Constants c
Definition Dispersion.m:45
void abort_mpi(const std::string str, const int err_type)
Definition common.cpp:90
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
uint64_t CellID
Definition definitions.h:54
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const int j
const int k
std::map< int, std::set< CellID > > onDccrgMapRemoteProcessGlobal
Definition gridGlue.cpp:11
std::vector< CellID > mapDccrgIdToFsGridGlobalID(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, CellID dccrgID)
Definition gridGlue.cpp:490
void feedBoundaryIntoFsGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
Definition gridGlue.cpp:516
std::map< int, std::set< CellID > > onFsgridMapRemoteProcessGlobal
Definition gridGlue.cpp:12
int getNumberOfCellsOnMaxRefLvl(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells)
Definition gridGlue.cpp:18
void feedMomentsIntoFsGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells, fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &moments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, bool dt2)
Definition gridGlue.cpp:165
std::map< CellID, std::vector< int64_t > > onFsgridMapCellsGlobal
Definition gridGlue.cpp:13
void getFieldsFromFsGrid(fsgrids::constvolspan volumefields, fsgrids::constbgbspan bgb, fsgrids::constegradpespan egradpe, fsgrids::constdmomentsspan dmoments, fsgrids::consttechnicalspan technical, FieldSolverGrid &fsgrid, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells)
Definition gridGlue.cpp:257
void copyMomentsToOutflow(fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &moments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
Definition gridGlue.cpp:35
void filterMoments(fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &moments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
Definition gridGlue.cpp:80
@ dVzdx
Definition gridGlue.hpp:45
@ EXGRADPE
Definition gridGlue.hpp:30
@ PERBZVOL
Definition gridGlue.hpp:17
@ dPERBYVOLdx
Definition gridGlue.hpp:21
@ dPERBYVOLdy
Definition gridGlue.hpp:22
@ dVxdx
Definition gridGlue.hpp:39
@ BGBZVOL
Definition gridGlue.hpp:29
@ dPERBZVOLdx
Definition gridGlue.hpp:24
@ dVydx
Definition gridGlue.hpp:42
@ N_FIELDSTOCOMMUNICATE
Definition gridGlue.hpp:48
@ EYGRADPE
Definition gridGlue.hpp:31
@ dVzdz
Definition gridGlue.hpp:47
@ EXVOL
Definition gridGlue.hpp:33
@ dVydy
Definition gridGlue.hpp:43
@ EZVOL
Definition gridGlue.hpp:35
@ PERBYVOL
Definition gridGlue.hpp:16
@ CURVATUREX
Definition gridGlue.hpp:36
@ EZGRADPE
Definition gridGlue.hpp:32
@ CURVATUREZ
Definition gridGlue.hpp:38
@ BGBXVOL
Definition gridGlue.hpp:27
@ PERBXVOL
Definition gridGlue.hpp:15
@ dPERBZVOLdz
Definition gridGlue.hpp:26
@ dPERBYVOLdz
Definition gridGlue.hpp:23
@ dVydz
Definition gridGlue.hpp:44
@ dVxdy
Definition gridGlue.hpp:40
@ BGBYVOL
Definition gridGlue.hpp:28
@ CURVATUREY
Definition gridGlue.hpp:37
@ dPERBZVOLdy
Definition gridGlue.hpp:25
@ EYVOL
Definition gridGlue.hpp:34
@ dVxdz
Definition gridGlue.hpp:41
@ dVzdy
Definition gridGlue.hpp:46
@ dPERBXVOLdz
Definition gridGlue.hpp:20
@ dPERBXVOLdx
Definition gridGlue.hpp:18
@ dPERBXVOLdy
Definition gridGlue.hpp:19
@ CURVATUREZ
Definition common.h:213
@ CURVATUREX
Definition common.h:211
@ CURVATUREY
Definition common.h:212
@ BGBYVOL
Definition common.h:379
@ BGBXVOL
Definition common.h:378
@ BGBZVOL
Definition common.h:380
std::span< const std::array< Real, fsgrids::dmoments::N_DMOMENTS > > constdmomentsspan
Definition common.h:449
@ EZGRADPE
Definition common.h:307
@ EYGRADPE
Definition common.h:306
@ EXGRADPE
Definition common.h:305
std::span< const std::array< Real, bgbfield::N_BGB > > constbgbspan
Definition common.h:445
@ N_MOMENTS
Definition common.h:320
@ RHOM
Definition common.h:312
std::span< technical > technicalspan
Definition common.h:452
std::span< const technical > consttechnicalspan
Definition common.h:453
@ dPERBZVOLdx
Definition common.h:413
@ dPERBXVOLdz
Definition common.h:409
@ dPERBZVOLdy
Definition common.h:414
@ dPERBZVOLdz
Definition common.h:415
@ PERBYVOL
Definition common.h:405
@ EZVOL
Definition common.h:418
@ dPERBYVOLdx
Definition common.h:410
@ EXVOL
Definition common.h:416
@ dPERBYVOLdy
Definition common.h:411
@ dPERBXVOLdy
Definition common.h:408
@ CURVATUREZ
Definition common.h:421
@ dPERBYVOLdz
Definition common.h:412
@ CURVATUREX
Definition common.h:419
@ PERBXVOL
Definition common.h:404
@ CURVATUREY
Definition common.h:420
@ dPERBXVOLdx
Definition common.h:407
@ EYVOL
Definition common.h:417
@ PERBZVOL
Definition common.h:406
@ dVydz
Definition common.h:363
@ dVydx
Definition common.h:361
@ dVzdz
Definition common.h:366
@ dVzdx
Definition common.h:364
@ dVxdy
Definition common.h:359
@ dVxdz
Definition common.h:360
@ dVzdy
Definition common.h:365
@ dVydy
Definition common.h:362
@ dVxdx
Definition common.h:358
std::span< const std::array< Real, fsgrids::volfields::N_VOL > > constvolspan
Definition common.h:451
std::span< const std::array< Real, fsgrids::egradpe::N_EGRADPE > > constegradpespan
Definition common.h:441
@ OUTER_BOUNDARY_PADDING
Definition common.h:493
static uint zcells_ini
Definition parameters.h:50
static int amrMaxSpatialRefLevel
Definition parameters.h:190
static uint ycells_ini
Definition parameters.h:49
static int maxFilteringPasses
Definition parameters.h:225
static uint xcells_ini
Definition parameters.h:48
static std::vector< int > numPasses
Definition parameters.h:236
static ARCH_HOSTDEV VecSimple< T > & operator+=(VecSimple< T > &l, const VecSimple< T > &r)