Block-Structured AMR Software Framework
AMReX_algoim_K.H
Go to the documentation of this file.
1 /*
2  * This file contains a modified version of Algoim developed by
3  * R. Saye, SIAM J. Sci. Comput., Vol. 37, No. 2, pp. A993-A1019,
4  * http://dx.doi.org/10.1137/140966290, https://algoim.github.io/.
5  *
6  * Algoim Copyright (c) 2018, The Regents of the University of
7  * California, through Lawrence Berkeley National Laboratory (subject
8  * to receipt of any required approvals from the U.S. Dept. of
9  * Energy). All rights reserved.
10  */
11 
12 #ifndef AMREX_ALGOIM_K_H_
13 #define AMREX_ALGOIM_K_H_
14 #include <AMReX_Config.H>
15 
16 #include <AMReX_algoim.H>
17 #include <AMReX_Array.H>
18 #include <limits>
19 #include <cfloat>
20 
21 namespace amrex::algoim {
22 
23 struct EBPlane
24 {
27 
28  EBPlane () = default;
29 
31  constexpr
32  EBPlane (GpuArray<Real,3> const& c, GpuArray<Real,3> const n) noexcept
33  : cent(c), norm(n)
34  {}
35 
37  constexpr
38  EBPlane (Real cx, Real cy, Real cz, Real nx, Real ny, Real nz) noexcept
39  : cent{cx,cy,cz}, norm{nx,ny,nz}
40  {}
41 
43  Real operator() (Real x, Real y, Real z) const noexcept
44  {
45  return (x-cent[0])*norm[0] + (y-cent[1])*norm[1] + (z-cent[2])*norm[2];
46  }
47 
49  Real operator() (GpuArray<Real,3> const& p) const noexcept
50  {
51  return (p[0]-cent[0])*norm[0] + (p[1]-cent[1])*norm[1]
52  + (p[2]-cent[2])*norm[2];
53  }
54 
56  Real grad (int d) const noexcept
57  {
58  return norm[d];
59  }
60 };
61 
63 {
64  struct Node
65  {
66  Real x, y, z, w;
67  };
68  int nnodes = 0;
70 
71  template<typename F>
73  Real
74  operator() (const F& f) const noexcept
75  {
76  Real r = 0;
77  for (int i = 0; i < nnodes; ++i) {
78  r += f(nodes[i].x,nodes[i].y,nodes[i].z) * nodes[i].w;
79  }
80  return r;
81  }
82 
83  template<typename F>
85  Real
86  eval (const F& f) const noexcept
87  {
88  Real r = 0;
89  for (int i = 0; i < nnodes; ++i) {
90  r += f(nodes[i].x,nodes[i].y,nodes[i].z) * nodes[i].w;
91  }
92  return r;
93  }
94 
95  // evalIntegrand records quadrature nodes when it is invoked by
96  // ImplicitIntegral
98  void
99  evalIntegrand (const GpuArray<Real,3>& x_, Real w_) noexcept
100  {
101  nodes[nnodes].x = x_[0];
102  nodes[nnodes].y = x_[1];
103  nodes[nnodes].z = x_[2];
104  nodes[nnodes].w = w_;
105  ++nnodes;
106  }
107 };
108 
109 namespace detail
110 {
111  template <class T>
113  void swap (T& a, T& b) noexcept {
114  T c(a); a=b; b=c;
115  }
116 
117  // Determines the sign conditions for restricting a (possibly
118  // already restricted) level set function, i.e., sgn_L and sgn_U
119  // in [R. Saye, High-Order Quadrature Methods for Implicitly
120  // Defined Surfaces and Volumes in Hyperrectangles, SIAM
121  // J. Sci. Comput., Vol. 37, No. 2, pp. A993-A1019,
122  // http://dx.doi.org/10.1137/140966290].
123  template<bool S>
125  void
126  determineSigns (bool positiveAbove, int sign, int& bottomSign, int& topSign) noexcept
127  {
128  // When evaluating a volume integral:
129  // If 0 integrating over the positive part:
130  // if positive above the height function: bottom = +/-, top = +
131  // if positive below the height function: bottom = +, top = +/-
132  // If integrating over the negative part:
133  // if positive above the height function: bottom = -, top = +/-
134  // if positive below the height function: bottom = +/-, top = -
135  // If integrating over both the positive and negative part (i.e. unrestricted in sign), keep it alive
136  if (S)
137  {
138  // When evaluating a surface integral,
139  // if the function is positive above the height function, then
140  // the bottom side must be negative and the top side must be positive;
141  // if the function is positive below the height function,
142  // then the bottom side must be positive and the top side must be negative.
143  bottomSign = positiveAbove? -1 : 1;
144  topSign = positiveAbove? 1 : -1;
145  } else {
146  if (sign == 1)
147  {
148  bottomSign = positiveAbove? 0 : 1;
149  topSign = positiveAbove? 1 : 0;
150  }
151  else if (sign == -1)
152  {
153  bottomSign = positiveAbove? -1 : 0;
154  topSign = positiveAbove? 0 : -1;
155  }
156  else {
157  bottomSign = topSign = 0;
158  }
159  }
160  }
161 } // namespace detail
162 
163 // PsiCode encodes sign information of restricted level set functions
164 // on particular sides of a hyperrectangle in a packed array of
165 // bits. The first N bits encodes side information, the N+1st bit is
166 // true iff the sign == 0, while the N+2nd bit stores the sign if sign
167 // != 0.
168 template<int N>
169 struct PsiCode
170 {
171  unsigned char bits = 0;
172 
174  PsiCode () noexcept = default;
175 
177  PsiCode (const GpuArray<int,N>& sides, int sign) noexcept
178  {
179  static_assert(N <= 3, "algoim::PsiCode: N must be <= 3");
180  for (int dim = 0; dim < N; ++dim) {
181  if (sides[dim] == 1) {
182  bits |= (1 << dim);
183  }
184  }
185  if (sign == 0) {
186  bits |= (1 << N);
187  } else {
188  bits &= ~(1 << N);
189  if (sign == 1) {
190  bits |= (1 << (N+1));
191  }
192  }
193  }
194 
195  // Modify an existing code by restriction in a particular dimension.
197  PsiCode (const PsiCode& i, int dim, int side, int sign) noexcept
198  : bits(i.bits)
199  {
200  if (side == 1) {
201  bits |= (1 << dim);
202  }
203  if (sign == 0) {
204  bits |= (1 << N);
205  } else {
206  bits &= ~(1 << N);
207  if (sign == 1) {
208  bits |= (1 << (N+1));
209  }
210  }
211  }
212 
214  int side (int dim) const noexcept
215  {
216  return bits & (1 << dim);
217  }
218 
220  int sign () const noexcept
221  {
222  return (bits & (1 << N)) ? 0 : ((bits & (1 << (N+1))) ? 1 : -1);
223  }
224 };
225 
226 template <int N>
228 {
229  static constexpr Real min (int /*dim*/) noexcept { return -0.5_rt; }
230 
231  static constexpr Real max (int /*dim*/) noexcept { return 0.5_rt; }
232 
233  static constexpr Real extent (int /*dim*/) noexcept { return 1.0_rt; }
234 
235  static constexpr GpuArray<Real,N> midpoint () noexcept {
236  return GpuArray<Real,N>{};
237  }
238 
239  static constexpr Real midpoint (int /*dim*/) noexcept { return 0.0_rt; }
240 
241  constexpr Real operator() (int side, int /*dim*/) const noexcept {
242  return (side == 0) ? -0.5_rt : 0.5_rt;
243  }
244 };
245 
246 struct Interval
247 {
248  Real alpha = std::numeric_limits<Real>::lowest();
249 };
250 
251 // M-dimensional integral of an N-dimensional function restricted to
252 // given implicitly defined domains
253 template<int M, int N, typename Phi, typename F, bool S>
255 {
256  const Phi* phi;
257  F* f;
259  GpuArray<PsiCode<N>,1 << (N - 1)> psi;
260  int psiCount;
262  int e0 = -1;
264  static constexpr int p = 4;
265 
266  // Prune the given set of functions by checking for the existence
267  // of the interface. If a function is uniformly positive or
268  // negative and is consistent with specified sign, it can be
269  // removed. If a function is uniformly positive or negative but
270  // inconsistent with specified sign, the domain of integration is
271  // empty.
273  bool prune () noexcept
274  {
275  static constexpr Real eps = std::numeric_limits<Real>::epsilon();
276  static constexpr Real almostone = 1.0-10.*eps;
277 
278  for (int i = 0; i < psiCount; )
279  {
280  GpuArray<Real,N> mid = xrange.midpoint();
281  Real dphi_max = 0.0_rt;
282  for (int dim = 0; dim < N; ++dim) {
283  if (free[dim]) {
284  dphi_max += std::abs(phi->grad(dim));
285  } else {
286  mid[dim] = xrange(psi[i].side(dim),dim);
287  }
288  }
289  dphi_max *= 0.5*almostone;
290  const Real phi_0 = (*phi)(mid);
291  bool uniform_sign = (phi_0 > dphi_max) || (phi_0 < -dphi_max);
292  if (uniform_sign)
293  {
294  if ((phi_0 >= 0.0 && psi[i].sign() >= 0) ||
295  (phi_0 <= 0.0 && psi[i].sign() <= 0) )
296  {
297  --psiCount;
299  }
300  else {
301  return false;
302  }
303  }
304  else {
305  ++i;
306  }
307  }
308  return true;
309  }
310 
311  // Gaussian quadrature for when the domain of integration is
312  // determined to be the entire M-dimensional cube.
314  void tensorProductIntegral () noexcept
315  {
316  constexpr Real gauss_x[4]={0.069431844202973712388026755553595247452_rt,
317  0.33000947820757186759866712044837765640_rt,
318  0.66999052179242813240133287955162234360_rt,
319  0.93056815579702628761197324444640475255_rt};
320  constexpr Real gauss_w[4]={0.173927422568726928686531974610999703618_rt,
321  0.326072577431273071313468025389000296382_rt,
322  0.326072577431273071313468025389000296382_rt,
323  0.173927422568726928686531974610999703618_rt};
324 
325  int nloops = 1;
326  for (int i = 0; i < M; ++i) {
327  nloops *= p;
328  }
329  GpuArray<int,M> i{}; // i is initialized to zero.
330  for (int iloop = 0; iloop < nloops; ++iloop)
331  {
333  Real w = 1.0_rt;
334  for (int dim = 0, k = 0; dim < N; ++dim) {
335  if (free[dim]) {
336  x[dim] = xrange.min(dim) + xrange.extent(dim) * gauss_x[i[k]];
337  w *= xrange.extent(dim) * gauss_w[i[k]];
338  ++k;
339  }
340  }
341  f->evalIntegrand(x, w);
342 
343  for (int m = M-1; m >= 0; --m) {
344  ++(i[m]);
345  if (i[m] < p) {
346  break;
347  } else {
348  i[m] = 0;
349  }
350  }
351  }
352  }
353 
354  // Given x, valid in all free variables barring e0, root find in
355  // the e0 direction on each of the implicit functions, and apply
356  // Gaussian quadrature to each segment. Weights are multiplied
357  // upon going back up the tree of recursive calls.
359  void evalIntegrand (GpuArray<Real,N> x, Real w) const noexcept
360  {
361  constexpr Real gauss_x[4]={0.069431844202973712388026755553595247452_rt,
362  0.33000947820757186759866712044837765640_rt,
363  0.66999052179242813240133287955162234360_rt,
364  0.93056815579702628761197324444640475255_rt};
365  constexpr Real gauss_w[4]={0.173927422568726928686531974610999703618_rt,
366  0.326072577431273071313468025389000296382_rt,
367  0.326072577431273071313468025389000296382_rt,
368  0.173927422568726928686531974610999703618_rt};
369 
370  // Each thread has its own storage for computing roots. These
371  // are not corrupted by the recursive chain of evalIntegrand()
372  // calls since each call is in a different templated
373  // namespace. Moreover, if using OpenMP tasking, each task is
374  // assumed tied and so one thread can only execute
375  // "evalIntegrand" from start to end uninterrupted.
376  GpuArray<Real,4> roots;
377 
378  // Surface integral
379  if (S)
380  {
381  AMREX_ASSERT(M == N && N >= 2); // x is thus valid in all variables except e0
382 
383  Real x_min = xrange.min(e0);
384  Real x_max = xrange.max(e0);
385  int nroots = 0;
386 
387  x[e0] = x_min;
388  Real phi_lo = (*phi)(x);
389  Real xroot = x[e0] - phi_lo / phi->grad(e0);
390  if (xroot > x_min && xroot < x_max) {
391  roots[nroots++] = xroot;
392  }
393 
394  AMREX_ASSERT(nroots <= 1);
395 
396  for (int i = 0; i < nroots; ++i)
397  {
398  x[e0] = roots[i];
399  Real mag = 0._rt;
400  for (int dim = 0; dim < N; ++dim) {
401  mag += phi->grad(dim)*phi->grad(dim);
402  }
403  mag = std::sqrt(mag);
404  f->evalIntegrand(x, (mag/std::abs(phi->grad(e0)))*w);
405  }
406 
407  return;
408  }
409 
410  // Partition [xmin(e0), xmax(e0)] by roots found
411  Real x_min = xrange.min(e0);
412  Real x_max = xrange.max(e0);
413  roots[0] = x_min;
414  int nroots = 1;
415  if (phi->grad(e0) != Real(0.0)) {
416  for (int i = 0; i < psiCount; ++i)
417  {
418  for (int dim = 0; dim < N; ++dim) {
419  if (!free[dim]) {
420  x[dim] = xrange(psi[i].side(dim),dim);
421  }
422  }
423  // x is now valid in all variables except e0
424  x[e0] = x_min;
425  Real phi_lo = (*phi)(x);
426  Real xroot = x[e0] - phi_lo / phi->grad(e0);
427  if (xroot > x_min && xroot < x_max) {
428  roots[nroots++] = xroot;
429  }
430  }
431  AMREX_ASSERT(nroots <= 3);
432  }
433  if (nroots == 3 && roots[1] > roots[2]) {
434  detail::swap(roots[1],roots[2]);
435  }
436  roots[nroots++] = x_max;
437 
438  // In rare cases, degenerate segments can be found, filter out with a tolerance
439  static constexpr Real eps = std::numeric_limits<Real>::epsilon();
440  constexpr Real tol = 50.0*eps;
441 
442  // Loop over segments of divided interval
443  for (int i = 0; i < nroots - 1; ++i)
444  {
445  if (roots[i+1] - roots[i] < tol) { continue; }
446 
447  // Evaluate sign of phi within segment and check for consistency with psi
448  bool okay = true;
449  x[e0] = (roots[i] + roots[i+1])*0.5;
450  for (int j = 0; j < psiCount && okay; ++j)
451  {
452  for (int dim = 0; dim < N; ++dim) {
453  if (!free[dim]) {
454  x[dim] = xrange(psi[j].side(dim), dim);
455  }
456  }
457  bool new_ok = ((*phi)(x) > 0.0) ? (psi[j].sign() >= 0) : (psi[j].sign() <= 0);
458  okay = okay && new_ok;
459  }
460  if (!okay) { continue; }
461 
462  for (int j = 0; j < p; ++j)
463  {
464  x[e0] = roots[i] + (roots[i+1] - roots[i]) * gauss_x[j];
465  Real gw = (roots[i+1] - roots[i]) * gauss_w[j];
466  f->evalIntegrand(x, w * gw);
467  }
468  }
469  }
470 
471  // Main calling engine; parameters with underscores are copied
472  // upon entry but modified internally in the ctor
473  template <int K = M, std::enable_if_t<K==1,int> = 0>
475  ImplicitIntegral (const Phi& phi_, F& f_, const GpuArray<bool,N>& free_,
476  const GpuArray<PsiCode<N>,1 << (N-1)>& psi_,
477  int psiCount_) noexcept
478  : phi(&phi_), f(&f_), free(free_), psi(psi_), psiCount(psiCount_),
479  xrange()
480  {
481  // For the one-dimensional base case, evaluate the
482  // bottom-level integral.
483  for (int dim = 0; dim < N; ++dim) {
484  if (free[dim]) {
485  e0 = dim;
486  }
487  }
489  }
490 
491  // Main calling engine; parameters with underscores are copied
492  // upon entry but modified internally in the ctor
493  template <int K = M, std::enable_if_t<(K>1),int> = 0>
495  ImplicitIntegral (const Phi& phi_, F& f_, const GpuArray<bool,N>& free_,
496  const GpuArray<PsiCode<N>,1 << (N-1)>& psi_,
497  int psiCount_) noexcept
498  : phi(&phi_), f(&f_), free(free_), psi(psi_), psiCount(psiCount_),
499  xrange()
500  {
501  // Establish interval bounds for prune() and remaining part of ctor.
502  for (int dim = 0; dim < N; ++dim)
503  {
504  if (free[dim])
505  {
506  xint[dim].alpha = xrange.midpoint(dim);
507  }
508  else
509  {
510  xint[dim].alpha = 0.0_rt;
511  }
512  }
513 
514  // Prune list of psi functions: if prune procedure returns
515  // false, then the domain of integration is empty.
516  if (!prune()) {
517  return;
518  }
519 
520  // If all psi functions were pruned, then the volumetric
521  // integral domain is the entire hyperrectangle.
522  if (psiCount == 0)
523  {
524  if (!S) {
526  }
527  return;
528  }
529 
530  // Among all monotone height function directions, choose the
531  // one that makes the associated height function look as flat
532  // as possible. This is a modification to the criterion
533  // presented in [R. Saye, High-Order Quadrature Methods for
534  // Implicitly Defined Surfaces and Volumes in Hyperrectangles,
535  // SIAM J. Sci. Comput., Vol. 37, No. 2, pp. A993-A1019,
536  // http://dx.doi.org/10.1137/140966290].
537  e0 = -1;
538  {
539  Real gmax = -1.;
540  for (int dim = 0; dim < N; ++dim) {
541  if (free[dim] && std::abs(phi->grad(dim)) > gmax) {
542  gmax = std::abs(phi->grad(dim));
543  e0 = dim;
544  }
545  }
546  }
547 
548  // Check compatibility with all implicit functions whilst
549  // simultaneously constructing new implicit functions.
550  GpuArray<PsiCode<N>,1 << (N-1)> newPsi;
551  int newPsiCount = 0;
552  for (int i = 0; i < psiCount; ++i)
553  {
554  // Evaluate gradient in an interval
555  for (int dim = 0; dim < N; ++dim) {
556  if (!free[dim]) {
557  xint[dim].alpha = xrange(psi[i].side(dim), dim);
558  }
559  }
560 
561  // w.z. We assume grad does not change.
562  int bottomSign, topSign;
563  detail::determineSigns<S>(phi->grad(e0) > 0.0, psi[i].sign(),
564  bottomSign, topSign);
565  // w.z. There are sides 0 and 1.
566  newPsi[newPsiCount++] = PsiCode<N>(psi[i], e0, 0, bottomSign);
567  newPsi[newPsiCount++] = PsiCode<N>(psi[i], e0, 1, topSign);
568  }
569 
570  // Dimension reduction call
571  GpuArray<bool,N> new_free = free;
572  new_free[e0] = false;
574  (*phi, *this, new_free, newPsi, newPsiCount);
575  }
576 };
577 
578 // Partial specialisation on M=0 as a dummy base case for the compiler
579 template<int N, typename Phi, typename F, bool S>
580 struct ImplicitIntegral<0,N,Phi,F,S>
581 {
583  ImplicitIntegral (const Phi&, F&, const GpuArray<bool,N>&,
584  const GpuArray<PsiCode<N>,1 << (N-1)>&,
585  int) noexcept {}
586 };
587 
589 QuadratureRule
590 quadGen (EBPlane const& phi) noexcept
591 {
592  QuadratureRule q;
593  GpuArray<bool,3> free{true,true,true};
594  GpuArray<PsiCode<3>,4> psi;
595  psi[0] = PsiCode<3>({0,0,0}, -1);
597  return q;
598 }
599 
601 QuadratureRule
602 quadGenSurf (EBPlane const& phi) noexcept
603 {
604  QuadratureRule q;
605  GpuArray<bool,3> free{true,true,true};
606  GpuArray<PsiCode<3>,4> psi;
607  psi[0] = PsiCode<3>({0,0,0}, -1);
609  return q;
610 }
611 
613 void set_regular (int i, int j, int k, Array4<Real> const& intg) noexcept
614 {
615  constexpr Real twelfth = 1._rt/12._rt;
616  constexpr Real offth = 1._rt/144._rt;
617  intg(i,j,k,i_S_x ) = 0.0_rt;
618  intg(i,j,k,i_S_y ) = 0.0_rt;
619  intg(i,j,k,i_S_z ) = 0.0_rt;
620  intg(i,j,k,i_S_x2 ) = twelfth;
621  intg(i,j,k,i_S_y2 ) = twelfth;
622  intg(i,j,k,i_S_z2 ) = twelfth;
623  intg(i,j,k,i_S_x_y ) = 0.0_rt;
624  intg(i,j,k,i_S_x_z ) = 0.0_rt;
625  intg(i,j,k,i_S_y_z ) = 0.0_rt;
626  intg(i,j,k,i_S_x2_y ) = 0.0_rt;
627  intg(i,j,k,i_S_x2_z ) = 0.0_rt;
628  intg(i,j,k,i_S_x_y2 ) = 0.0_rt;
629  intg(i,j,k,i_S_y2_z ) = 0.0_rt;
630  intg(i,j,k,i_S_x_z2 ) = 0.0_rt;
631  intg(i,j,k,i_S_y_z2 ) = 0.0_rt;
632  intg(i,j,k,i_S_x2_y2) = offth;
633  intg(i,j,k,i_S_x2_z2) = offth;
634  intg(i,j,k,i_S_y2_z2) = offth;
635  intg(i,j,k,i_S_xyz ) = 0.0_rt;
636 }
637 
639 void set_regular_surface (int i, int j, int k, Array4<Real> const& sintg) noexcept
640 {
641  sintg(i,j,k,i_B_x ) = 0.0_rt;
642  sintg(i,j,k,i_B_y ) = 0.0_rt;
643  sintg(i,j,k,i_B_z ) = 0.0_rt;
644  sintg(i,j,k,i_B_x_y ) = 0.0_rt;
645  sintg(i,j,k,i_B_x_z ) = 0.0_rt;
646  sintg(i,j,k,i_B_y_z ) = 0.0_rt;
647  sintg(i,j,k,i_B_xyz ) = 0.0_rt;
648 }
649 
650 }
651 
652 #endif
#define AMREX_ASSERT(EX)
Definition: AMReX_BLassert.H:38
#define AMREX_FORCE_INLINE
Definition: AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition: AMReX_GpuQualifiers.H:20
#define AMREX_GPU_HOST
Definition: AMReX_GpuQualifiers.H:17
void free(void *)
#define abs(x)
Definition: complex-type.h:85
static int f(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition: AMReX_SundialsIntegrator.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void swap(T &a, T &b) noexcept
Definition: AMReX_algoim_K.H:113
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void determineSigns(bool positiveAbove, int sign, int &bottomSign, int &topSign) noexcept
Definition: AMReX_algoim_K.H:126
Definition: AMReX_algoim.cpp:6
static constexpr int i_B_xyz
Definition: AMReX_algoim.H:42
static constexpr int i_S_y_z2
Definition: AMReX_algoim.H:26
static constexpr int i_S_y_z
Definition: AMReX_algoim.H:20
AMREX_GPU_HOST_DEVICE QuadratureRule quadGen(EBPlane const &phi) noexcept
Definition: AMReX_algoim_K.H:590
static constexpr int i_S_x2
Definition: AMReX_algoim.H:15
static constexpr int i_S_x_y
Definition: AMReX_algoim.H:18
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_regular_surface(int i, int j, int k, Array4< Real > const &sintg) noexcept
Definition: AMReX_algoim_K.H:639
static constexpr int i_S_y
Definition: AMReX_algoim.H:13
static constexpr int i_S_x_z
Definition: AMReX_algoim.H:19
static constexpr int i_B_z
Definition: AMReX_algoim.H:38
static constexpr int i_S_x_y2
Definition: AMReX_algoim.H:23
static constexpr int i_S_xyz
Definition: AMReX_algoim.H:30
static constexpr int i_S_y2_z2
Definition: AMReX_algoim.H:29
static constexpr int i_B_x_y
Definition: AMReX_algoim.H:39
static constexpr int i_B_x_z
Definition: AMReX_algoim.H:40
static constexpr int i_S_x2_y2
Definition: AMReX_algoim.H:27
static constexpr int i_S_x2_z2
Definition: AMReX_algoim.H:28
static constexpr int i_S_x
Definition: AMReX_algoim.H:12
static constexpr int i_S_y2_z
Definition: AMReX_algoim.H:24
static constexpr int i_S_x2_y
Definition: AMReX_algoim.H:21
static constexpr int i_B_y_z
Definition: AMReX_algoim.H:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_regular(int i, int j, int k, Array4< Real > const &intg) noexcept
Definition: AMReX_algoim_K.H:613
static constexpr int i_B_x
Definition: AMReX_algoim.H:36
static constexpr int i_S_z
Definition: AMReX_algoim.H:14
static constexpr int i_S_z2
Definition: AMReX_algoim.H:17
static constexpr int i_S_x_z2
Definition: AMReX_algoim.H:25
static constexpr int i_S_x2_z
Definition: AMReX_algoim.H:22
AMREX_GPU_HOST_DEVICE QuadratureRule quadGenSurf(EBPlane const &phi) noexcept
Definition: AMReX_algoim_K.H:602
static constexpr int i_B_y
Definition: AMReX_algoim.H:37
static constexpr int i_S_y2
Definition: AMReX_algoim.H:16
constexpr double eps
Definition: AMReX_MLNodeLap_K.H:64
constexpr Real almostone
Definition: AMReX_MLNodeLap_K.H:66
static constexpr int M
Definition: AMReX_OpenBC.H:13
real(kind=amrex_real), parameter twelfth
Definition: AMReX_constants_mod.f90:32
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Return the square root of a complex number.
Definition: AMReX_GpuComplex.H:373
Definition: AMReX_FabArrayCommI.H:841
Definition: AMReX_Array4.H:61
Definition: AMReX_algoim_K.H:228
static constexpr Real min(int) noexcept
Definition: AMReX_algoim_K.H:229
static constexpr Real max(int) noexcept
Definition: AMReX_algoim_K.H:231
static constexpr GpuArray< Real, N > midpoint() noexcept
Definition: AMReX_algoim_K.H:235
constexpr Real operator()(int side, int) const noexcept
Definition: AMReX_algoim_K.H:241
static constexpr Real midpoint(int) noexcept
Definition: AMReX_algoim_K.H:239
static constexpr Real extent(int) noexcept
Definition: AMReX_algoim_K.H:233
Definition: AMReX_algoim_K.H:24
GpuArray< Real, 3 > cent
Definition: AMReX_algoim_K.H:25
constexpr AMREX_GPU_HOST_DEVICE EBPlane(Real cx, Real cy, Real cz, Real nx, Real ny, Real nz) noexcept
Definition: AMReX_algoim_K.H:38
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real grad(int d) const noexcept
Definition: AMReX_algoim_K.H:56
constexpr AMREX_GPU_HOST_DEVICE EBPlane(GpuArray< Real, 3 > const &c, GpuArray< Real, 3 > const n) noexcept
Definition: AMReX_algoim_K.H:32
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real operator()(Real x, Real y, Real z) const noexcept
Definition: AMReX_algoim_K.H:43
GpuArray< Real, 3 > norm
Definition: AMReX_algoim_K.H:26
AMREX_GPU_HOST_DEVICE ImplicitIntegral(const Phi &, F &, const GpuArray< bool, N > &, const GpuArray< PsiCode< N >, 1<<(N-1)> &, int) noexcept
Definition: AMReX_algoim_K.H:583
Definition: AMReX_algoim_K.H:255
static constexpr int p
Definition: AMReX_algoim_K.H:264
BoundingBox< N > xrange
Definition: AMReX_algoim_K.H:261
F * f
Definition: AMReX_algoim_K.H:257
const Phi * phi
Definition: AMReX_algoim_K.H:256
AMREX_GPU_HOST_DEVICE ImplicitIntegral(const Phi &phi_, F &f_, const GpuArray< bool, N > &free_, const GpuArray< PsiCode< N >, 1<<(N-1)> &psi_, int psiCount_) noexcept
Definition: AMReX_algoim_K.H:475
int e0
Definition: AMReX_algoim_K.H:262
AMREX_GPU_HOST_DEVICE void evalIntegrand(GpuArray< Real, N > x, Real w) const noexcept
Definition: AMReX_algoim_K.H:359
int psiCount
Definition: AMReX_algoim_K.H:260
GpuArray< bool, N > free
Definition: AMReX_algoim_K.H:258
GpuArray< Interval, N > xint
Definition: AMReX_algoim_K.H:263
AMREX_GPU_HOST_DEVICE bool prune() noexcept
Definition: AMReX_algoim_K.H:273
AMREX_GPU_HOST_DEVICE void tensorProductIntegral() noexcept
Definition: AMReX_algoim_K.H:314
GpuArray< PsiCode< N >, 1<<(N - 1)> psi
Definition: AMReX_algoim_K.H:259
Definition: AMReX_algoim_K.H:247
Real alpha
Definition: AMReX_algoim_K.H:248
Definition: AMReX_algoim_K.H:170
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int side(int dim) const noexcept
Definition: AMReX_algoim_K.H:214
AMREX_GPU_HOST_DEVICE constexpr AMREX_FORCE_INLINE PsiCode() noexcept=default
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int sign() const noexcept
Definition: AMReX_algoim_K.H:220
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE PsiCode(const PsiCode &i, int dim, int side, int sign) noexcept
Definition: AMReX_algoim_K.H:197
unsigned char bits
Definition: AMReX_algoim_K.H:171
Definition: AMReX_algoim_K.H:65
Real w
Definition: AMReX_algoim_K.H:66
Real z
Definition: AMReX_algoim_K.H:66
Real y
Definition: AMReX_algoim_K.H:66
Real x
Definition: AMReX_algoim_K.H:66
Definition: AMReX_algoim_K.H:63
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void evalIntegrand(const GpuArray< Real, 3 > &x_, Real w_) noexcept
Definition: AMReX_algoim_K.H:99
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real operator()(const F &f) const noexcept
Definition: AMReX_algoim_K.H:74
AMREX_GPU_HOST AMREX_FORCE_INLINE Real eval(const F &f) const noexcept
Definition: AMReX_algoim_K.H:86
int nnodes
Definition: AMReX_algoim_K.H:68
GpuArray< Node, 256 > nodes
Definition: AMReX_algoim_K.H:69