Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_Loop.H
Go to the documentation of this file.
1#ifndef AMREX_LOOP_H_
2#define AMREX_LOOP_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_Box.H>
7#include <AMReX_Extension.H>
8
9namespace amrex {
10
12namespace loop_detail {
13
14 // call_f_intvect_inner
15
16 template <typename F, std::size_t...Ns, class...Args>
18 auto call_f_intvect_inner (std::index_sequence<Ns...>, F const& f, IntVectND<1> iv, Args...args)
19 noexcept -> decltype(f(0, 0, 0, args...))
20 {
21 f(iv[0], 0, 0, args...);
22 }
23
24 template <typename F, std::size_t...Ns, class...Args>
26 auto call_f_intvect_inner (std::index_sequence<Ns...>, F const& f, IntVectND<2> iv, Args...args)
27 noexcept -> decltype(f(0, 0, 0, args...))
28 {
29 f(iv[0], iv[1], 0, args...);
30 }
31
32 template <typename F, int dim, std::size_t...Ns, class...Args>
34 auto call_f_intvect_inner (std::index_sequence<Ns...>, F const& f, IntVectND<dim> iv, Args...args)
35 noexcept -> decltype(f(iv, args...))
36 {
37 f(iv, args...);
38 }
39
40 template <typename F, int dim, std::size_t...Ns, class...Args>
42 auto call_f_intvect_inner (std::index_sequence<Ns...>, F const& f, IntVectND<dim> iv, Args...args)
43 noexcept -> decltype(f(iv[Ns]..., args...))
44 {
45 f(iv[Ns]..., args...);
46 }
47
48 // call_f_intvect
49
50 template <typename F, int dim>
52 auto call_f_intvect (F const& f, IntVectND<dim> iv)
53 noexcept -> decltype(call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv))
54 {
55 call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv);
56 }
57
58 // call_f_intvect_ncomp
59
60 template <typename F, int dim>
62 auto call_f_intvect_ncomp (F const& f, IntVectND<dim> iv, int n)
63 noexcept -> decltype(call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, 0))
64 {
65 call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n);
66 }
67
68 // call_f_intvect_inner_cpu
69
70 template <typename F, std::size_t...Ns, class...Args>
72 auto call_f_intvect_inner_cpu (std::index_sequence<Ns...>, F const& f, IntVectND<1> iv, Args...args)
73 noexcept -> decltype(f(0, 0, 0, args...))
74 {
75 f(iv[0], 0, 0, args...);
76 }
77
78 template <typename F, std::size_t...Ns, class...Args>
80 auto call_f_intvect_inner_cpu (std::index_sequence<Ns...>, F const& f, IntVectND<2> iv, Args...args)
81 noexcept -> decltype(f(0, 0, 0, args...))
82 {
83 f(iv[0], iv[1], 0, args...);
84 }
85
86 template <typename F, int dim, std::size_t...Ns, class...Args>
88 auto call_f_intvect_inner_cpu (std::index_sequence<Ns...>, F const& f, IntVectND<dim> iv, Args...args)
89 noexcept -> decltype(f(iv, args...))
90 {
91 f(iv, args...);
92 }
93
94 template <typename F, int dim, std::size_t...Ns, class...Args>
96 auto call_f_intvect_inner_cpu (std::index_sequence<Ns...>, F const& f, IntVectND<dim> iv, Args...args)
97 noexcept -> decltype(f(iv[Ns]..., args...))
98 {
99 f(iv[Ns]..., args...);
100 }
101
102 // call_f_intvect_cpu
103
104 template <typename F, int dim>
106 auto call_f_intvect_cpu (F const& f, IntVectND<dim> iv)
107 noexcept -> decltype(call_f_intvect_inner_cpu(std::make_index_sequence<dim>(), f, iv))
108 {
109 call_f_intvect_inner_cpu(std::make_index_sequence<dim>(), f, iv);
110 }
111
112 // call_f_intvect_ncomp_cpu
113
114 template <typename F, int dim>
116 auto call_f_intvect_ncomp_cpu (F const& f, IntVectND<dim> iv, int n)
117 noexcept -> decltype(call_f_intvect_inner_cpu(std::make_index_sequence<dim>(), f, iv, 0))
118 {
119 call_f_intvect_inner_cpu(std::make_index_sequence<dim>(), f, iv, n);
120 }
121}
123
124template <class F>
127void Loop (Dim3 lo, Dim3 hi, F const& f) noexcept
128{
129 for (int k = lo.z; k <= hi.z; ++k) {
130 for (int j = lo.y; j <= hi.y; ++j) {
131 for (int i = lo.x; i <= hi.x; ++i) {
132 f(i,j,k);
133 }}}
134}
135
136template <class F>
139void Loop (Dim3 lo, Dim3 hi, int ncomp, F const& f) noexcept
140{
141 for (int n = 0; n < ncomp; ++n) {
142 for (int k = lo.z; k <= hi.z; ++k) {
143 for (int j = lo.y; j <= hi.y; ++j) {
144 for (int i = lo.x; i <= hi.x; ++i) {
145 f(i,j,k,n);
146 }}}}
147}
148
149template <class F>
152void LoopConcurrent (Dim3 lo, Dim3 hi, F const& f) noexcept
153{
154 for (int k = lo.z; k <= hi.z; ++k) {
155 for (int j = lo.y; j <= hi.y; ++j) {
157 for (int i = lo.x; i <= hi.x; ++i) {
158 f(i,j,k);
159 }}}
160}
161
162template <class F>
165void LoopConcurrent (Dim3 lo, Dim3 hi, int ncomp, F const& f) noexcept
166{
167 for (int n = 0; n < ncomp; ++n) {
168 for (int k = lo.z; k <= hi.z; ++k) {
169 for (int j = lo.y; j <= hi.y; ++j) {
171 for (int i = lo.x; i <= hi.x; ++i) {
172 f(i,j,k,n);
173 }}}}
174}
175
177namespace loop_detail {
178
179template <int idim, typename L, int dim>
181void Loop_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv) noexcept
182{
183 if constexpr (idim == 1) {
184 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
185 call_f_intvect(f,iv);
186 }
187 } else if constexpr (idim == 2) {
188 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
189 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
190 call_f_intvect(f,iv);
191 }}
192 } else if constexpr (idim == 3) {
193 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
194 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
195 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
196 call_f_intvect(f,iv);
197 }}}
198 } else {
199 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
200 Loop_impND<idim-1>(f, lo, hi, iv);
201 }
202 }
203}
204
205}
207
208template <class F, int dim>
211void Loop (BoxND<dim> const& bx, F const& f) noexcept
212{
213 const auto lo = amrex::lbound_iv(bx);
214 const auto hi = amrex::ubound_iv(bx);
216 loop_detail::Loop_impND<dim>(f, lo, hi, iv);
217}
218
220namespace loop_detail {
221
222template <int idim, typename L, int dim>
224void Loop_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv, int n) noexcept
225{
226 if constexpr (idim == 1) {
227 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
228 call_f_intvect_ncomp(f,iv,n);
229 }
230 } else if constexpr (idim == 2) {
231 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
232 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
233 call_f_intvect_ncomp(f,iv,n);
234 }}
235 } else if constexpr (idim == 3) {
236 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
237 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
238 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
239 call_f_intvect_ncomp(f,iv,n);
240 }}}
241 } else {
242 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
243 Loop_impND<idim-1>(f, lo, hi, iv, n);
244 }
245 }
246}
247
248}
250
251template <class F, int dim>
254void Loop (BoxND<dim> const& bx, int ncomp, F const& f) noexcept
255{
256 const auto lo = amrex::lbound_iv(bx);
257 const auto hi = amrex::ubound_iv(bx);
259 for (int n = 0; n < ncomp; ++n) {
260 loop_detail::Loop_impND<dim>(f, lo, hi, iv, n);
261 }
262}
263
265namespace loop_detail {
266
267template <int idim, typename L, int dim>
269void LoopConcurrent_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv) noexcept
270{
271 if constexpr (idim == 1) {
273 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
274 call_f_intvect(f,iv);
275 }
276 } else if constexpr (idim == 2) {
277 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
279 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
280 call_f_intvect(f,iv);
281 }}
282 } else if constexpr (idim == 3) {
283 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
284 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
286 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
287 call_f_intvect(f,iv);
288 }}}
289 } else {
290 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
291 LoopConcurrent_impND<idim-1>(f, lo, hi, iv);
292 }
293 }
294}
295
296}
298
299template <class F, int dim>
302void LoopConcurrent (BoxND<dim> const& bx, F const& f) noexcept
303{
304 const auto lo = amrex::lbound_iv(bx);
305 const auto hi = amrex::ubound_iv(bx);
307 loop_detail::LoopConcurrent_impND<dim>(f, lo, hi, iv);
308}
309
311namespace loop_detail {
312
313template <int idim, typename L, int dim>
315void LoopConcurrent_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv, int n) noexcept
316{
317 if constexpr (idim == 1) {
319 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
320 call_f_intvect_ncomp(f,iv,n);
321 }
322 } else if constexpr (idim == 2) {
323 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
325 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
326 call_f_intvect_ncomp(f,iv,n);
327 }}
328 } else if constexpr (idim == 3) {
329 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
330 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
332 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
333 call_f_intvect_ncomp(f,iv,n);
334 }}}
335 } else {
336 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
337 LoopConcurrent_impND<idim-1>(f, lo, hi, iv, n);
338 }
339 }
340}
341
342}
344
345template <class F, int dim>
348void LoopConcurrent (BoxND<dim> const& bx, int ncomp, F const& f) noexcept
349{
350 const auto lo = amrex::lbound_iv(bx);
351 const auto hi = amrex::ubound_iv(bx);
353 for (int n = 0; n < ncomp; ++n) {
354 loop_detail::LoopConcurrent_impND<dim>(f, lo, hi, iv, n);
355 }
356}
357
358// The functions above are __host__ __device__ functions. If f is not a
359// __host__ __device__ function, we will get warning about calling __host__
360// function from a __host__ __device__ function. This is ugly. To get rid
361// of the warning, we have to use the functions below for those situations.
362
363template <class F>
365void LoopOnCpu (Dim3 lo, Dim3 hi, F const& f) noexcept
366{
367 for (int k = lo.z; k <= hi.z; ++k) {
368 for (int j = lo.y; j <= hi.y; ++j) {
369 for (int i = lo.x; i <= hi.x; ++i) {
370 f(i,j,k);
371 }}}
372}
373
374template <class F>
376void LoopOnCpu (Dim3 lo, Dim3 hi, int ncomp, F const& f) noexcept
377{
378 for (int n = 0; n < ncomp; ++n) {
379 for (int k = lo.z; k <= hi.z; ++k) {
380 for (int j = lo.y; j <= hi.y; ++j) {
381 for (int i = lo.x; i <= hi.x; ++i) {
382 f(i,j,k,n);
383 }}}}
384}
385
386template <class F>
388void LoopConcurrentOnCpu (Dim3 lo, Dim3 hi, F const& f) noexcept
389{
390 for (int k = lo.z; k <= hi.z; ++k) {
391 for (int j = lo.y; j <= hi.y; ++j) {
393 for (int i = lo.x; i <= hi.x; ++i) {
394 f(i,j,k);
395 }}}
396}
397
398template <class F>
400void LoopConcurrentOnCpu (Dim3 lo, Dim3 hi, int ncomp, F const& f) noexcept
401{
402 for (int n = 0; n < ncomp; ++n) {
403 for (int k = lo.z; k <= hi.z; ++k) {
404 for (int j = lo.y; j <= hi.y; ++j) {
406 for (int i = lo.x; i <= hi.x; ++i) {
407 f(i,j,k,n);
408 }}}}
409}
410
412namespace loop_detail {
413
414template <int idim, typename L, int dim>
416void LoopOnCpu_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv) noexcept
417{
418 if constexpr (idim == 1) {
419 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
420 call_f_intvect_cpu(f,iv);
421 }
422 } else if constexpr (idim == 2) {
423 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
424 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
425 call_f_intvect_cpu(f,iv);
426 }}
427 } else if constexpr (idim == 3) {
428 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
429 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
430 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
431 call_f_intvect_cpu(f,iv);
432 }}}
433 } else {
434 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
435 LoopOnCpu_impND<idim-1>(f, lo, hi, iv);
436 }
437 }
438}
439
440}
442
443template <class F, int dim>
445void LoopOnCpu (BoxND<dim> const& bx, F const& f) noexcept
446{
447 const auto lo = amrex::lbound_iv(bx);
448 const auto hi = amrex::ubound_iv(bx);
450 loop_detail::LoopOnCpu_impND<dim>(f, lo, hi, iv);
451}
452
454namespace loop_detail {
455
456template <int idim, typename L, int dim>
458void LoopOnCpu_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv, int n) noexcept
459{
460 if constexpr (idim == 1) {
461 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
462 call_f_intvect_ncomp_cpu(f,iv,n);
463 }
464 } else if constexpr (idim == 2) {
465 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
466 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
467 call_f_intvect_ncomp_cpu(f,iv,n);
468 }}
469 } else if constexpr (idim == 3) {
470 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
471 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
472 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
473 call_f_intvect_ncomp_cpu(f,iv,n);
474 }}}
475 } else {
476 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
477 LoopOnCpu_impND<idim-1>(f, lo, hi, iv, n);
478 }
479 }
480}
481
482}
484
485template <class F, int dim>
487void LoopOnCpu (BoxND<dim> const& bx, int ncomp, F const& f) noexcept
488{
489 const auto lo = amrex::lbound_iv(bx);
490 const auto hi = amrex::ubound_iv(bx);
492 for (int n = 0; n < ncomp; ++n) {
493 loop_detail::LoopOnCpu_impND<dim>(f, lo, hi, iv, n);
494 }
495}
496
498namespace loop_detail {
499
500template <int idim, typename L, int dim>
502void LoopConcurrentOnCpu_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv) noexcept
503{
504 if constexpr (idim == 1) {
506 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
507 call_f_intvect_cpu(f,iv);
508 }
509 } else if constexpr (idim == 2) {
510 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
512 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
513 call_f_intvect_cpu(f,iv);
514 }}
515 } else if constexpr (idim == 3) {
516 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
517 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
519 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
520 call_f_intvect_cpu(f,iv);
521 }}}
522 } else {
523 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
524 LoopConcurrentOnCpu_impND<idim-1>(f, lo, hi, iv);
525 }
526 }
527}
528
529}
531
532template <class F, int dim>
534void LoopConcurrentOnCpu (BoxND<dim> const& bx, F const& f) noexcept
535{
536 const auto lo = amrex::lbound_iv(bx);
537 const auto hi = amrex::ubound_iv(bx);
539 loop_detail::LoopConcurrentOnCpu_impND<dim>(f, lo, hi, iv);
540}
541
543namespace loop_detail {
544
545template <int idim, typename L, int dim>
547void LoopConcurrentOnCpu_impND (L const& f, IntVectND<dim> const lo, IntVectND<dim> const hi, IntVectND<dim> iv, int n) noexcept
548{
549 if constexpr (idim == 1) {
551 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
552 call_f_intvect_ncomp_cpu(f,iv,n);
553 }
554 } else if constexpr (idim == 2) {
555 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
557 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
558 call_f_intvect_ncomp_cpu(f,iv,n);
559 }}
560 } else if constexpr (idim == 3) {
561 for (int i2 = lo[2], h2 = hi[2]; i2 <= h2; ++i2) { iv[2] = i2;
562 for (int i1 = lo[1], h1 = hi[1]; i1 <= h1; ++i1) { iv[1] = i1;
564 for (int i0 = lo[0], h0 = hi[0]; i0 <= h0; ++i0) { iv[0] = i0;
565 call_f_intvect_ncomp_cpu(f,iv,n);
566 }}}
567 } else {
568 for (int id = lo[idim-1], hd = hi[idim-1]; id <= hd; ++id) { iv[idim-1] = id;
569 LoopConcurrentOnCpu_impND<idim-1>(f, lo, hi, iv, n);
570 }
571 }
572}
573
574}
576
577template <class F, int dim>
579void LoopConcurrentOnCpu (BoxND<dim> const& bx, int ncomp, F const& f) noexcept
580{
581 const auto lo = amrex::lbound_iv(bx);
582 const auto hi = amrex::ubound_iv(bx);
584 for (int n = 0; n < ncomp; ++n) {
585 loop_detail::LoopConcurrentOnCpu_impND<dim>(f, lo, hi, iv, n);
586 }
587}
588
589#include <AMReX_Loop.nolint.H>
590
591}
592
593#endif
#define AMREX_PRAGMA_SIMD
Definition AMReX_Extension.H:80
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_ATTRIBUTE_FLATTEN_FOR
Definition AMReX_Extension.H:151
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
A Rectangular Domain on an Integer Lattice.
Definition AMReX_Box.H:49
An Integer Vector in dim-Dimensional Space.
Definition AMReX_IntVect.H:57
Definition AMReX_Amr.cpp:49
__host__ __device__ IntVectND< dim > lbound_iv(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1905
__host__ __device__ IntVectND< dim > ubound_iv(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1914
void LoopConcurrentOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:388
__host__ __device__ void Loop(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:127
void LoopOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:365
__host__ __device__ void LoopConcurrent(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:152
Definition AMReX_Dim3.H:12