OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
BoxLibParticle.hpp
Go to the documentation of this file.
1 //
2 // Class BoxLibParticle
3 // Particle class for AMReX. It works together with BoxLibLayout.
4 // The class does the scatter and gather operations of attributes
5 // to and from the grid. Ippl implements the same functionality in the
6 // attribute class.
7 //
8 // Copyright (c) 2016 - 2020, Matthias Frey, Uldis Locans, Paul Scherrer Institut, Villigen PSI, Switzerland
9 // All rights reserved
10 //
11 // Implemented as part of the PhD thesis
12 // "Precise Simulations of Multibunches in High Intensity Cyclotrons"
13 //
14 // This file is part of OPAL.
15 //
16 // OPAL is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
23 //
24 #ifndef BOXLIB_PARTICLE_HPP
25 #define BOXLIB_PARTICLE_HPP
26 
28 
29 #include <AMReX_BLFort.H>
30 #include <AMReX_MultiFabUtil.H>
31 #include <AMReX_MultiFabUtil_F.H>
32 #include <AMReX_Interpolater.H>
33 #include <AMReX_FillPatchUtil.H>
34 
35 template<class PLayout>
37 {
38  AssignDensityTimer_m = IpplTimings::getTimer("AMR AssignDensity");
39 }
40 
41 
42 template<class PLayout>
44 {
45  AssignDensityTimer_m = IpplTimings::getTimer("AMR AssignDensity");
46 }
47 
48 
49 template<class PLayout>
50 template<class FT, unsigned Dim, class PT>
53  int lbase, int lfine,
54  const ParticleAttrib<int>& pbin, int bin)
55 {
56  if ( lbase == lfine ) {
57  this->scatter(attrib, *(f[lbase].get()), pp, pbin, bin, lbase);
58  return;
59  }
60 
61  const PLayout *layout_p = &this->getLayout();
62  int nGrow = layout_p->refRatio(lbase)[0];
63 
64  AmrScalarFieldContainer_t tmp(lfine+1);
65  for (int lev = lbase; lev <= lfine; ++lev) {
66 
67  f[lev]->setVal(0.0, f[lev]->nGrow());
68 
69  const AmrGrid_t& ba = f[lev]->boxArray();
70  const AmrProcMap_t& dm = f[lev]->DistributionMap();
71  tmp[lev].reset(new AmrField_t(ba, dm, 1, nGrow));
72  tmp[lev]->setVal(0.0, nGrow);
73  }
74 
75  this->AssignDensityFort(attrib, tmp, lbase, 1, lfine, pbin, bin);
76 
77  for (int lev = lbase; lev <= lfine; ++lev)
78  AmrField_t::Copy(*f[lev], *tmp[lev], 0, 0, f[lev]->nComp(), f[lev]->nGrow());
79 }
80 
81 
82 template<class PLayout>
83 template <class FT, unsigned Dim, class PT>
86  const ParticleAttrib<int>& pbin, int bin,
87  int level)
88 {
89  const AmrGrid_t& ba = f.boxArray();
90  const AmrProcMap_t& dmap = f.DistributionMap();
91 
92  AmrField_t tmp(ba, dmap, f.nComp(), 1);
93  tmp.setVal(0.0, 1);
94 
95  this->AssignCellDensitySingleLevelFort(attrib, tmp, level, pbin, bin);
96 
97  f.setVal(0.0, f.nGrow());
98 
99  AmrField_t::Copy(f, tmp, 0, 0, f.nComp(), f.nGrow());
100 }
101 
102 
103 template<class PLayout>
104 template<class FT, unsigned Dim, class PT>
107  int lbase, int lfine)
108 {
109  this->InterpolateFort(attrib, f, lbase, lfine);
110 }
111 
112 
113 // Function from BoxLib adjusted to work with Ippl BoxLibParticle class
114 // Scatter the particle attribute pa on the grid
115 template<class PLayout>
116 template <class AType>
118  AmrScalarFieldContainer_t& mf_to_be_filled,
119  int lev_min, int ncomp, int finest_level,
120  const ParticleAttrib<int>& pbin, int bin) const
121 {
122 // BL_PROFILE("AssignDensityFort()");
123  IpplTimings::startTimer(AssignDensityTimer_m);
124  const PLayout *layout_p = &this->getLayout();
125 
126  // not done in amrex
127  int rho_index = 0;
128 
129  amrex::PhysBCFunct cphysbc, fphysbc;
130  int lo_bc[] = {INT_DIR, INT_DIR, INT_DIR}; // periodic boundaries
131  int hi_bc[] = {INT_DIR, INT_DIR, INT_DIR};
132  amrex::Vector<amrex::BCRec> bcs(1, amrex::BCRec(lo_bc, hi_bc));
133  amrex::PCInterp mapper;
134 
135  AmrScalarFieldContainer_t tmp(finest_level+1);
136  for (int lev = lev_min; lev <= finest_level; ++lev) {
137  const AmrGrid_t& ba = mf_to_be_filled[lev]->boxArray();
138  const AmrProcMap_t& dm = mf_to_be_filled[lev]->DistributionMap();
139  tmp[lev].reset(new AmrField_t(ba, dm, 1, 0));
140  tmp[lev]->setVal(0.0);
141  }
142 
143  for (int lev = lev_min; lev <= finest_level; ++lev) {
144  AssignCellDensitySingleLevelFort(pa, *mf_to_be_filled[lev], lev, pbin, bin, 1, 0);
145 
146  if (lev < finest_level) {
147  amrex::InterpFromCoarseLevel(*tmp[lev+1], 0.0, *mf_to_be_filled[lev],
148  rho_index, rho_index, ncomp,
149  layout_p->Geom(lev), layout_p->Geom(lev+1),
150  cphysbc, fphysbc,
151  layout_p->refRatio(lev), &mapper, bcs);
152  }
153 
154  if (lev > lev_min) {
155  // Note - this will double count the mass on the coarse level in
156  // regions covered by the fine level, but this will be corrected
157  // below in the call to average_down.
158  amrex::sum_fine_to_coarse(*mf_to_be_filled[lev],
159  *mf_to_be_filled[lev-1],
160  rho_index, 1, layout_p->refRatio(lev-1),
161  layout_p->Geom(lev-1), layout_p->Geom(lev));
162  }
163 
164  mf_to_be_filled[lev]->plus(*tmp[lev], rho_index, ncomp, 0);
165  }
166 
167  for (int lev = finest_level - 1; lev >= lev_min; --lev) {
168  amrex::average_down(*mf_to_be_filled[lev+1],
169  *mf_to_be_filled[lev], rho_index, ncomp, layout_p->refRatio(lev));
170  }
171 
172  IpplTimings::stopTimer(AssignDensityTimer_m);
173 }
174 
175 
176 // This is the single-level version for cell-centered density
177 template<class PLayout>
178 template <class AType>
180  AmrField_t& mf_to_be_filled,
181  int level,
182  const ParticleAttrib<int>& pbin,
183  int bin,
184  int ncomp,
185  int /*particle_lvl_offset*/) const
186 {
187 // BL_PROFILE("ParticleContainer<NStructReal, NStructInt, NArrayReal, NArrayInt>::AssignCellDensitySingleLevelFort()");
188 
189  const PLayout *layout_p = &this->getLayout();
190 
191  AmrField_t* mf_pointer;
192 
193  if (layout_p->OnSameGrids(level, mf_to_be_filled)) {
194  // If we are already working with the internal mf defined on the
195  // particle_box_array, then we just work with this.
196  mf_pointer = &mf_to_be_filled;
197  }
198  else {
199  // If mf_to_be_filled is not defined on the particle_box_array, then we need
200  // to make a temporary here and copy into mf_to_be_filled at the end.
201  mf_pointer = new AmrField_t(layout_p->ParticleBoxArray(level),
202  layout_p->ParticleDistributionMap(level),
203  ncomp, mf_to_be_filled.nGrow());
204  }
205 
206  // We must have ghost cells for each FAB so that a particle in one grid can spread
207  // its effect to an adjacent grid by first putting the value into ghost cells of its
208  // own grid. The mf->sumBoundary call then adds the value from one grid's ghost cell
209  // to another grid's valid region.
210  if (mf_pointer->nGrow() < 1)
211  throw OpalException("BoxLibParticle::AssignCellDensitySingleLevelFort()",
212  "Must have at least one ghost cell when in AssignCellDensitySingleLevelFort");
213 
214  const AmrGeometry_t& gm = layout_p->Geom(level);
215  const AmrReal_t* plo = gm.ProbLo();
216 // const AmrReal_t* dx_particle = layout_p->Geom(level + particle_lvl_offset).CellSize();
217  const AmrReal_t* dx = gm.CellSize();
218 
219  if (gm.isAnyPeriodic() && ! gm.isAllPeriodic()) {
220  throw OpalException("BoxLibParticle::AssignCellDensitySingleLevelFort()",
221  "Problem must be periodic in no or all directions");
222  }
223 
224  for (amrex::MFIter mfi(*mf_pointer); mfi.isValid(); ++mfi) {
225  (*mf_pointer)[mfi].setVal(0);
226  }
227 
228  //loop trough particles and distribute values on the grid
229  const ParticleLevelCounter_t& LocalNumPerLevel = this->getLocalNumPerLevel();
230  size_t lBegin = LocalNumPerLevel.begin(level);
231  size_t lEnd = LocalNumPerLevel.end(level);
232 
233  AmrReal_t inv_dx[3] = { 1.0 / dx[0], 1.0 / dx[1], 1.0 / dx[2] };
234  double lxyz[3] = { 0.0, 0.0, 0.0 };
235  double wxyz_hi[3] = { 0.0, 0.0, 0.0 };
236  double wxyz_lo[3] = { 0.0, 0.0, 0.0 };
237  int ijk[3] = {0, 0, 0};
238 
239  for (size_t ip = lBegin; ip < lEnd; ++ip) {
240 
241  if ( bin > -1 && pbin[ip] != bin )
242  continue;
243 
244  const int grid = this->Grid[ip];
245  FArrayBox_t& fab = (*mf_pointer)[grid];
246 
247  // not callable:
248  // begin amrex_deposit_cic(pbx.data(), nstride, N, fab.dataPtr(), box.loVect(), box.hiVect(), plo, dx);
249  for (int i = 0; i < 3; ++i) {
250  lxyz[i] = ( this->R[ip](i) - plo[i] ) * inv_dx[i] + 0.5;
251  ijk[i] = lxyz[i];
252  wxyz_hi[i] = lxyz[i] - ijk[i];
253  wxyz_lo[i] = 1.0 - wxyz_hi[i];
254  }
255 
256  int& i = ijk[0];
257  int& j = ijk[1];
258  int& k = ijk[2];
259 
260  AmrIntVect_t i1(i-1, j-1, k-1);
261  AmrIntVect_t i2(i-1, j-1, k);
262  AmrIntVect_t i3(i-1, j, k-1);
263  AmrIntVect_t i4(i-1, j, k);
264  AmrIntVect_t i5(i, j-1, k-1);
265  AmrIntVect_t i6(i, j-1, k);
266  AmrIntVect_t i7(i, j, k-1);
267  AmrIntVect_t i8(i, j, k);
268 
269  fab(i1, 0) += wxyz_lo[0]*wxyz_lo[1]*wxyz_lo[2]*pa[ip];
270  fab(i2, 0) += wxyz_lo[0]*wxyz_lo[1]*wxyz_hi[2]*pa[ip];
271  fab(i3, 0) += wxyz_lo[0]*wxyz_hi[1]*wxyz_lo[2]*pa[ip];
272  fab(i4, 0) += wxyz_lo[0]*wxyz_hi[1]*wxyz_hi[2]*pa[ip];
273  fab(i5, 0) += wxyz_hi[0]*wxyz_lo[1]*wxyz_lo[2]*pa[ip];
274  fab(i6, 0) += wxyz_hi[0]*wxyz_lo[1]*wxyz_hi[2]*pa[ip];
275  fab(i7, 0) += wxyz_hi[0]*wxyz_hi[1]*wxyz_lo[2]*pa[ip];
276  fab(i8, 0) += wxyz_hi[0]*wxyz_hi[1]*wxyz_hi[2]*pa[ip];
277  // end of amrex_deposit_cic
278  }
279 
280  mf_pointer->SumBoundary(gm.periodicity());
281 
282  // Only multiply the first component by (1/vol) because this converts mass
283  // to density. If there are additional components (like velocity), we don't
284  // want to divide those by volume.
285  const AmrReal_t vol = D_TERM(dx[0], *dx[1], *dx[2]);
286 
287  mf_pointer->mult(1.0/vol, 0, 1, mf_pointer->nGrow());
288 
289  // If mf_to_be_filled is not defined on the particle_box_array, then we need
290  // to copy here from mf_pointer into mf_to_be_filled. I believe that we don't
291  // need any information in ghost cells so we don't copy those.
292  if (mf_pointer != &mf_to_be_filled) {
293  mf_to_be_filled.copy(*mf_pointer,0,0,ncomp);
294  delete mf_pointer;
295  }
296 }
297 
298 
299 template<class PLayout>
300 template <class AType>
302  AmrVectorFieldContainer_t& mesh_data,
303  int lev_min, int lev_max)
304 {
305  for (int lev = lev_min; lev <= lev_max; ++lev) {
306  if ( lev > 0 )
307  InterpolateMultiLevelFort(pa, mesh_data, lev);
308  else
309  InterpolateSingleLevelFort(pa, mesh_data[lev], lev);
310  }
311 }
312 
313 
314 template<class PLayout>
315 template <class AType>
317  AmrVectorField_t& mesh_data, int lev)
318 {
319  for (std::size_t i = 0; i < mesh_data.size(); ++i) {
320  if (mesh_data[i]->nGrow() < 1)
321  throw OpalException("BoxLibParticle::InterpolateSingleLevelFort()",
322  "Must have at least one ghost cell when in InterpolateSingleLevelFort");
323  }
324 
325  PLayout *layout_p = &this->getLayout();
326 
327  const AmrGeometry_t& gm = layout_p->Geom(lev);
328  const AmrReal_t* plo = gm.ProbLo();
329  const AmrReal_t* dx = gm.CellSize();
330 
331  //loop trough particles and distribute values on the grid
332  const ParticleLevelCounter_t& LocalNumPerLevel = this->getLocalNumPerLevel();
333  size_t lBegin = LocalNumPerLevel.begin(lev);
334  size_t lEnd = LocalNumPerLevel.end(lev);
335 
336  // make sure that boundaries are filled!
337  for (std::size_t i = 0; i < mesh_data.size(); ++i) {
338  mesh_data[i]->FillBoundary(gm.periodicity());
339  }
340 
341  AmrReal_t inv_dx[3] = { 1.0 / dx[0], 1.0 / dx[1], 1.0 / dx[2] };
342  double lxyz[3] = { 0.0, 0.0, 0.0 };
343  double wxyz_hi[3] = { 0.0, 0.0, 0.0 };
344  double wxyz_lo[3] = { 0.0, 0.0, 0.0 };
345  int ijk[3] = {0, 0, 0};
346  for (size_t ip = lBegin; ip < lEnd; ++ip) {
347 
348  const int grid = this->Grid[ip];
349  FArrayBox_t& exfab = (*mesh_data[0])[grid];
350  FArrayBox_t& eyfab = (*mesh_data[1])[grid];
351  FArrayBox_t& ezfab = (*mesh_data[2])[grid];
352 
353 
354  // not callable
355  // begin amrex_interpolate_cic(pbx.data(), nstride, N, fab.dataPtr(), box.loVect(), box.hiVect(), nComp, plo, dx);
356  for (int i = 0; i < 3; ++i) {
357  lxyz[i] = ( this->R[ip](i) - plo[i] ) * inv_dx[i] + 0.5;
358  ijk[i] = lxyz[i];
359  wxyz_hi[i] = lxyz[i] - ijk[i];
360  wxyz_lo[i] = 1.0 - wxyz_hi[i];
361  }
362 
363  int& i = ijk[0];
364  int& j = ijk[1];
365  int& k = ijk[2];
366 
367  AmrIntVect_t i1(i-1, j-1, k-1);
368  AmrIntVect_t i2(i-1, j-1, k);
369  AmrIntVect_t i3(i-1, j, k-1);
370  AmrIntVect_t i4(i-1, j, k);
371  AmrIntVect_t i5(i, j-1, k-1);
372  AmrIntVect_t i6(i, j-1, k);
373  AmrIntVect_t i7(i, j, k-1);
374  AmrIntVect_t i8(i, j, k);
375 
376  pa[ip](0) = wxyz_lo[0]*wxyz_lo[1]*wxyz_lo[2]*exfab(i1) +
377  wxyz_lo[0]*wxyz_lo[1]*wxyz_hi[2]*exfab(i2) +
378  wxyz_lo[0]*wxyz_hi[1]*wxyz_lo[2]*exfab(i3) +
379  wxyz_lo[0]*wxyz_hi[1]*wxyz_hi[2]*exfab(i4) +
380  wxyz_hi[0]*wxyz_lo[1]*wxyz_lo[2]*exfab(i5) +
381  wxyz_hi[0]*wxyz_lo[1]*wxyz_hi[2]*exfab(i6) +
382  wxyz_hi[0]*wxyz_hi[1]*wxyz_lo[2]*exfab(i7) +
383  wxyz_hi[0]*wxyz_hi[1]*wxyz_hi[2]*exfab(i8);
384 
385  pa[ip](1) = wxyz_lo[0]*wxyz_lo[1]*wxyz_lo[2]*eyfab(i1) +
386  wxyz_lo[0]*wxyz_lo[1]*wxyz_hi[2]*eyfab(i2) +
387  wxyz_lo[0]*wxyz_hi[1]*wxyz_lo[2]*eyfab(i3) +
388  wxyz_lo[0]*wxyz_hi[1]*wxyz_hi[2]*eyfab(i4) +
389  wxyz_hi[0]*wxyz_lo[1]*wxyz_lo[2]*eyfab(i5) +
390  wxyz_hi[0]*wxyz_lo[1]*wxyz_hi[2]*eyfab(i6) +
391  wxyz_hi[0]*wxyz_hi[1]*wxyz_lo[2]*eyfab(i7) +
392  wxyz_hi[0]*wxyz_hi[1]*wxyz_hi[2]*eyfab(i8);
393 
394  pa[ip](2) = wxyz_lo[0]*wxyz_lo[1]*wxyz_lo[2]*ezfab(i1) +
395  wxyz_lo[0]*wxyz_lo[1]*wxyz_hi[2]*ezfab(i2) +
396  wxyz_lo[0]*wxyz_hi[1]*wxyz_lo[2]*ezfab(i3) +
397  wxyz_lo[0]*wxyz_hi[1]*wxyz_hi[2]*ezfab(i4) +
398  wxyz_hi[0]*wxyz_lo[1]*wxyz_lo[2]*ezfab(i5) +
399  wxyz_hi[0]*wxyz_lo[1]*wxyz_hi[2]*ezfab(i6) +
400  wxyz_hi[0]*wxyz_hi[1]*wxyz_lo[2]*ezfab(i7) +
401  wxyz_hi[0]*wxyz_hi[1]*wxyz_hi[2]*ezfab(i8);
402  // end amrex_interpolate_cic
403  }
404 }
405 
406 
407 template<class PLayout>
408 template <class AType>
410  AmrVectorFieldContainer_t& mesh_data,
411  int lev)
412 {
413  for (std::size_t i = 0; i < mesh_data[lev].size(); ++i) {
414  if (mesh_data[lev][i]->nGrow() < 1)
415  throw OpalException("BoxLibParticle::InterpolateMultiLevelFort()",
416  "Must have at least one ghost cell when in InterpolateMultiLevelFort");
417  }
418 
419  PLayout *layout_p = &this->getLayout();
420 
421  const AmrGeometry_t& gm = layout_p->Geom(lev);
422  const AmrReal_t* plo = gm.ProbLo();
423  const AmrReal_t* fdx = gm.CellSize();
424  const AmrReal_t* cdx = layout_p->Geom(lev-1).CellSize();
425  const AmrReal_t* cplo = layout_p->Geom(lev-1).ProbLo();
426 
427  //loop trough particles and distribute values on the grid
428  const ParticleLevelCounter_t& LocalNumPerLevel = this->getLocalNumPerLevel();
429  size_t lBegin = LocalNumPerLevel.begin(lev);
430  size_t lEnd = LocalNumPerLevel.end(lev);
431 
432  // make sure that boundaries are filled!
433  for (std::size_t i = 0; i < mesh_data[lev].size(); ++i) {
434  mesh_data[lev][i]->FillBoundary(gm.periodicity());
435  }
436 
437  AmrReal_t inv_fdx[3] = { 1.0 / fdx[0], 1.0 / fdx[1], 1.0 / fdx[2] };
438  AmrReal_t inv_cdx[3] = { 1.0 / cdx[0], 1.0 / cdx[1], 1.0 / cdx[2] };
439  double lxyz[3] = { 0.0, 0.0, 0.0 };
440  double wxyz_hi[3] = { 0.0, 0.0, 0.0 };
441  double wxyz_lo[3] = { 0.0, 0.0, 0.0 };
442  int ijk[3] = { 0, 0, 0 };
443 
444  const AmrGrid_t& fba = mesh_data[lev][0]->boxArray();
445  const AmrProcMap_t& fdmap = mesh_data[lev][0]->DistributionMap();
446  AmrGrid_t cba = fba;
447  cba.coarsen(AmrIntVect_t(2, 2, 2));
448 
449  AmrField_t cmesh_exdata(cba, fdmap,
450  mesh_data[lev][0]->nComp(),
451  mesh_data[lev][0]->nGrow());
452 
453  cmesh_exdata.setVal(0.0, 0, 1, mesh_data[lev][0]->nGrow());
454  cmesh_exdata.copy(*mesh_data[lev-1][0], 0, 0, 1, 1, 1);
455  cmesh_exdata.FillBoundary(gm.periodicity());
456 
457  AmrField_t cmesh_eydata(cba, fdmap,
458  mesh_data[lev][1]->nComp(),
459  mesh_data[lev][1]->nGrow());
460  cmesh_eydata.setVal(0.0, 0, 1, mesh_data[lev][1]->nGrow());
461  cmesh_eydata.copy(*mesh_data[lev-1][1], 0, 0, 1, 1, 1);
462  cmesh_eydata.FillBoundary(gm.periodicity());
463 
464  AmrField_t cmesh_ezdata(cba, fdmap,
465  mesh_data[lev][2]->nComp(),
466  mesh_data[lev][2]->nGrow());
467  cmesh_ezdata.setVal(0.0, 0, 1, mesh_data[lev][2]->nGrow());
468  cmesh_ezdata.copy(*mesh_data[lev-1][2], 0, 0, 1, 1, 1);
469  cmesh_ezdata.FillBoundary(gm.periodicity());
470 
471  for (size_t ip = lBegin; ip < lEnd; ++ip) {
472 
473  const int grid = this->Grid[ip];
474 
475  FArrayBox_t& exfab = (*(mesh_data[lev][0]))[grid];
476  FArrayBox_t& eyfab = (*(mesh_data[lev][1]))[grid];
477  FArrayBox_t& ezfab = (*(mesh_data[lev][2]))[grid];
478 
479  FArrayBox_t& cexfab = cmesh_exdata[grid];
480  FArrayBox_t& ceyfab = cmesh_eydata[grid];
481  FArrayBox_t& cezfab = cmesh_ezdata[grid];
482 
483  const typename PLayout::basefab_t& mfab = (*layout_p->getLevelMask(lev))[grid];
484 
485  // not callable
486  // begin amrex_interpolate_cic(pbx.data(), nstride, N, fab.dataPtr(), box.loVect(), box.hiVect(), nComp, plo, dx);
487  for (int ii = 0; ii < 3; ++ii) {
488  lxyz[ii] = ( this->R[ip](ii) - plo[ii] ) * inv_fdx[ii] + 0.5;
489  ijk[ii] = lxyz[ii];
490  wxyz_hi[ii] = lxyz[ii] - ijk[ii];
491  wxyz_lo[ii] = 1.0 - wxyz_hi[ii];
492  }
493 
494  int& i = ijk[0];
495  int& j = ijk[1];
496  int& k = ijk[2];
497 
498  bool use_coarse = false;
499 
500  // AMReX: electrostatic_pic_3d.f90
501  // use the coarse E near the level boundary
502  if ( mfab(AmrIntVect_t(i-1, j-1, k-1)) == 1 ) {
503 
504 
505  for (int ii = 0; ii < 3; ++ii) {
506  lxyz[ii] = ( this->R[ip](ii) - cplo[ii] ) * inv_cdx[ii] + 0.5;
507  ijk[ii] = lxyz[ii];
508  wxyz_hi[ii] = lxyz[ii] - ijk[ii];
509  wxyz_lo[ii] = 1.0 - wxyz_hi[ii];
510  }
511  use_coarse = true;
512  }
513 
514  AmrIntVect_t i1(i-1, j-1, k-1);
515  AmrIntVect_t i3(i-1, j, k-1);
516  AmrIntVect_t i5(i, j-1, k-1);
517  AmrIntVect_t i7(i, j, k-1);
518 
519  AmrIntVect_t i2(i-1, j-1, k);
520  AmrIntVect_t i4(i-1, j, k);
521  AmrIntVect_t i6(i, j-1, k);
522  AmrIntVect_t i8(i, j, k);
523  if ( use_coarse ) {
524  pa[ip](0) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * cexfab(i1) +
525  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * cexfab(i3) +
526  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * cexfab(i5) +
527  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * cexfab(i7) +
528  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * cexfab(i2) +
529  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * cexfab(i4) +
530  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * cexfab(i6) +
531  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * cexfab(i8);
532 
533  pa[ip](1) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * ceyfab(i1) +
534  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * ceyfab(i3) +
535  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * ceyfab(i5) +
536  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * ceyfab(i7) +
537  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * ceyfab(i2) +
538  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * ceyfab(i4) +
539  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * ceyfab(i6) +
540  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * ceyfab(i8);
541 
542  pa[ip](2) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * cezfab(i1) +
543  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * cezfab(i3) +
544  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * cezfab(i5) +
545  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * cezfab(i7) +
546  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * cezfab(i2) +
547  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * cezfab(i4) +
548  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * cezfab(i6) +
549  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * cezfab(i8);
550  } else {
551  pa[ip](0) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * exfab(i1) +
552  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * exfab(i3) +
553  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * exfab(i5) +
554  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * exfab(i7) +
555  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * exfab(i2) +
556  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * exfab(i4) +
557  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * exfab(i6) +
558  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * exfab(i8);
559 
560  pa[ip](1) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * eyfab(i1) +
561  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * eyfab(i3) +
562  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * eyfab(i5) +
563  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * eyfab(i7) +
564  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * eyfab(i2) +
565  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * eyfab(i4) +
566  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * eyfab(i6) +
567  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * eyfab(i8);
568 
569  pa[ip](2) = wxyz_lo[0] * wxyz_lo[1] * wxyz_lo[2] * ezfab(i1) +
570  wxyz_lo[0] * wxyz_hi[1] * wxyz_lo[2] * ezfab(i3) +
571  wxyz_hi[0] * wxyz_lo[1] * wxyz_lo[2] * ezfab(i5) +
572  wxyz_hi[0] * wxyz_hi[1] * wxyz_lo[2] * ezfab(i7) +
573  wxyz_lo[0] * wxyz_lo[1] * wxyz_hi[2] * ezfab(i2) +
574  wxyz_lo[0] * wxyz_hi[1] * wxyz_hi[2] * ezfab(i4) +
575  wxyz_hi[0] * wxyz_lo[1] * wxyz_hi[2] * ezfab(i6) +
576  wxyz_hi[0] * wxyz_hi[1] * wxyz_hi[2] * ezfab(i8);
577  }
578  // end amrex_interpolate_cic
579  }
580 }
581 
582 #endif
amr::AmrField_t AmrField_t
Definition: PBunchDefs.h:34
bool scatter(Communicate &, InputIterator, InputIterator, RandomIterator, int *, int *, const ScatterOp &)
Definition: GlobalComm.hpp:353
amrex::IntVect AmrIntVect_t
Definition: AmrDefs.h:48
PLayout::AmrIntVect_t AmrIntVect_t
AmrParticleBase< PLayout >::AmrField_t AmrField_t
PLayout::AmrProcMap_t AmrProcMap_t
void AssignCellDensitySingleLevelFort(ParticleAttrib< AType > &pa, AmrField_t &mf, int level, const ParticleAttrib< int > &pbin, int bin=-1, int ncomp=1, int particle_lvl_offset=0) const
PLayout::AmrGeometry_t AmrGeometry_t
IpplTimings::TimerRef AssignDensityTimer_m
void InterpolateMultiLevelFort(ParticleAttrib< AType > &pa, AmrVectorFieldContainer_t &mesh_data, int lev)
void AssignDensityFort(ParticleAttrib< AType > &pa, AmrScalarFieldContainer_t &mf_to_be_filled, int lev_min, int ncomp, int finest_level, const ParticleAttrib< int > &pbin, int bin=-1) const
AmrParticleBase< PLayout >::AmrVectorField_t AmrVectorField_t
void gather(ParticleAttrib< FT > &attrib, AmrVectorFieldContainer_t &f, ParticleAttrib< Vektor< PT, Dim > > &pp, int lbase, int lfine)
PLayout::AmrGrid_t AmrGrid_t
AmrParticleBase< PLayout >::AmrVectorFieldContainer_t AmrVectorFieldContainer_t
void InterpolateFort(ParticleAttrib< AType > &pa, AmrVectorFieldContainer_t &mesh_data, int lev_min, int lev_max)
amrex::FArrayBox FArrayBox_t
PLayout::AmrReal_t AmrReal_t
void scatter(ParticleAttrib< FT > &attrib, AmrScalarFieldContainer_t &f, ParticleAttrib< Vektor< PT, Dim > > &pp, int lbase, int lfine, const ParticleAttrib< int > &pbin, int bin=-1)
AmrParticleBase< PLayout >::AmrScalarFieldContainer_t AmrScalarFieldContainer_t
void InterpolateSingleLevelFort(ParticleAttrib< AType > &pa, AmrVectorField_t &mesh_data, int lev)
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Definition: Vektor.h:32
static TimerRef getTimer(const char *nm)
Definition: IpplTimings.h:182
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187