Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_CompositeSystemUtil.H
Go to the documentation of this file.
1#ifndef AMREX_COMPOSITE_SYSTEM_UTIL_H_
2#define AMREX_COMPOSITE_SYSTEM_UTIL_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_AlgMG.H>
8#include <AMReX_ParmParse.H>
9#include <AMReX_Scan.H>
10#include <AMReX_SpMatrix.H>
11#include <AMReX_Vector.H>
12
13#include <algorithm>
14#include <array>
15#include <fstream>
16#include <iomanip>
17#include <limits>
18#include <map>
19#include <sstream>
20#include <string>
21
30
32
34struct Triplet { Long row; Long col; Real val; };
35
37inline std::string to_sci (double x)
38{
39 std::ostringstream os;
40 os << std::scientific << std::setprecision(6) << x;
41 return os.str();
42}
43
49{
51 Long nrows = 0;
55
56 [[nodiscard]] Long nnz () const { return values.size(); }
57
60 void define (Long a_row_begin, Long a_nrows, Vector<Triplet> trips)
61 {
62 row_begin = a_row_begin;
63 nrows = a_nrows;
64 std::sort(trips.begin(), trips.end(), [] (Triplet const& a, Triplet const& b) {
65 return (a.row < b.row) || (a.row == b.row && a.col < b.col);
66 });
67 row_offset.assign(nrows+1, 0);
68 col_index.clear();
69 values.clear();
70 col_index.reserve(trips.size());
71 values.reserve(trips.size());
72 Long prev_row = -1, prev_col = -1;
73 for (auto const& t : trips) {
74 AMREX_ALWAYS_ASSERT(t.row >= row_begin && t.row < row_begin+nrows);
75 if (t.row == prev_row && t.col == prev_col) {
76 values.back() += t.val;
77 } else {
78 col_index.push_back(t.col);
79 values.push_back(t.val);
80 ++row_offset[t.row-row_begin+1];
81 prev_row = t.row;
82 prev_col = t.col;
83 }
84 }
85 for (Long r = 0; r < nrows; ++r) { row_offset[r+1] += row_offset[r]; }
86 }
87
89 void toSpMatrix (SpMatrix<Real>& mat, Vector<Long> const& rank_offset) const
90 {
92 csr.mat.resize(values.size());
93 csr.col_index.resize(col_index.size());
94 csr.row_offset.resize(row_offset.size());
95 csr.nnz = nnz();
96 Gpu::copyAsync(Gpu::hostToDevice, values.begin(), values.end(), csr.mat.begin());
97 Gpu::copyAsync(Gpu::hostToDevice, col_index.begin(), col_index.end(), csr.col_index.begin());
100 mat.define(AlgPartition(rank_offset), std::move(csr), CsrSorted{true});
101 }
102};
103
110 MPI_Comm comm)
111{
112 const int nprocs = ParallelDescriptor::NProcs(comm);
113 if (nprocs == 1) { return std::move(trips); }
114#ifdef AMREX_USE_MPI
115 const int myproc = ParallelDescriptor::MyProc(comm);
116 Vector<Vector<Triplet>> sendbuf(nprocs);
117 Vector<Triplet> local;
118 for (auto const& t : trips) {
119 auto it = std::upper_bound(rank_offset.begin(), rank_offset.end(), t.row);
120 const int p = static_cast<int>(it - rank_offset.begin()) - 1;
121 AMREX_ALWAYS_ASSERT(p >= 0 && p < nprocs); // row in [0, total)
122 if (p == myproc) { local.push_back(t); } else { sendbuf[p].push_back(t); }
123 }
124 trips.clear();
125 // Counts in triplets (one MPI element per triplet), checked against int
126 constexpr Long int_max = std::numeric_limits<int>::max();
127 Vector<int> sendcnt(nprocs), recvcnt(nprocs), sdispl(nprocs), rdispl(nprocs);
128 for (int p = 0; p < nprocs; ++p) {
129 AMREX_ALWAYS_ASSERT(sendbuf[p].size() <= int_max);
130 sendcnt[p] = static_cast<int>(sendbuf[p].size());
131 }
132 MPI_Alltoall(sendcnt.data(), 1, MPI_INT, recvcnt.data(), 1, MPI_INT, comm);
133 Long stot = 0, rtot = 0;
134 for (int p = 0; p < nprocs; ++p) {
135 sdispl[p] = static_cast<int>(stot); stot += sendcnt[p];
136 rdispl[p] = static_cast<int>(rtot); rtot += recvcnt[p];
137 }
138 AMREX_ALWAYS_ASSERT(stot <= int_max && rtot <= int_max);
139 Vector<Triplet> sbuf;
140 sbuf.reserve(stot);
141 for (auto const& b : sendbuf) { sbuf.insert(sbuf.end(), b.begin(), b.end()); }
142 sendbuf.clear();
143 const Long nlocal = local.size();
144 local.resize(nlocal + rtot);
145 MPI_Datatype ttype;
146 MPI_Type_contiguous(int(sizeof(Triplet)), MPI_BYTE, &ttype);
147 MPI_Type_commit(&ttype);
148 MPI_Alltoallv(sbuf.data(), sendcnt.data(), sdispl.data(), ttype,
149 local.data()+nlocal, recvcnt.data(), rdispl.data(), ttype, comm);
150 MPI_Type_free(&ttype);
151 return local;
152#else
153 amrex::ignore_unused(rank_offset);
154 return std::move(trips);
155#endif
156}
157
171 Gpu::DeviceVector<Real>& vals, Long row_begin, Long nrows,
172 Vector<Long> const& rank_offset, MPI_Comm comm,
173 SpMatrix<Real>& mat)
174{
175 BL_PROFILE("composite::triplets_to_spmatrix");
176 AMREX_ALWAYS_ASSERT(rows.size() == cols.size() && rows.size() == vals.size());
177 const Long row_end = row_begin + nrows;
178
179 if (ParallelDescriptor::NProcs(comm) > 1) {
180 // Gather the triplets of other ranks' rows, exchange them on the
181 // host and append the ones received
182 const auto n = Long(rows.size());
183 auto const* pr = rows.data();
184 auto const* pc = cols.data();
185 auto const* pv = vals.data();
187 auto* ppos = pos.data();
188 const Long nsend = Scan::PrefixSum<Long>(n,
189 [=] AMREX_GPU_DEVICE (Long i) -> Long { return (pr[i] < row_begin || pr[i] >= row_end) ? 1 : 0; },
190 [=] AMREX_GPU_DEVICE (Long i, Long const& x) { ppos[i] = x; },
192 Gpu::DeviceVector<Triplet> dsend(nsend);
193 auto* ps = dsend.data();
194 amrex::ParallelFor(n, [=] AMREX_GPU_DEVICE (Long i) noexcept
195 {
196 if (pr[i] < row_begin || pr[i] >= row_end) {
197 ps[ppos[i]] = Triplet{.row = pr[i], .col = pc[i], .val = pv[i]};
198 }
199 });
200 Vector<Triplet> hsend(nsend);
201 Gpu::copyAsync(Gpu::deviceToHost, dsend.begin(), dsend.end(), hsend.begin());
203 Vector<Triplet> const hrecv = exchange_triplets(std::move(hsend), rank_offset, comm);
204 const auto nrecv = Long(hrecv.size());
205 if (nrecv > 0) {
206 Gpu::DeviceVector<Triplet> drecv(nrecv);
207 Gpu::copyAsync(Gpu::hostToDevice, hrecv.begin(), hrecv.end(), drecv.begin());
208 rows.resize(n+nrecv);
209 cols.resize(n+nrecv);
210 vals.resize(n+nrecv);
211 auto const* pt = drecv.data();
212 auto* r = rows.data();
213 auto* c = cols.data();
214 auto* v = vals.data();
215 amrex::ParallelFor(nrecv, [=] AMREX_GPU_DEVICE (Long i) noexcept
216 {
217 r[n+i] = pt[i].row;
218 c[n+i] = pt[i].col;
219 v[n+i] = pt[i].val;
220 });
222 }
223 }
224
225 // Bucket the triplet indices by row
226 const auto ntrip = Long(rows.size());
227 auto const* pr = rows.data();
228 auto const* pc = cols.data();
229 auto const* pv = vals.data();
230 Gpu::DeviceVector<int> cnt(nrows, 0);
231 Gpu::DeviceVector<Long> start(nrows+1);
232 auto* pcnt = cnt.data();
233 auto* pstart = start.data();
234 amrex::ParallelFor(ntrip, [=] AMREX_GPU_DEVICE (Long i) noexcept
235 {
236 if (pr[i] >= row_begin && pr[i] < row_end) {
237 Gpu::Atomic::AddNoRet(pcnt + (pr[i]-row_begin), 1);
238 }
239 });
240 const Long n_owned = Scan::PrefixSum<Long>(nrows,
241 [=] AMREX_GPU_DEVICE (Long r) -> Long { return pcnt[r]; },
242 [=] AMREX_GPU_DEVICE (Long r, Long const& x) { pstart[r] = x; },
244 amrex::ParallelFor(nrows+1, [=] AMREX_GPU_DEVICE (Long r) noexcept
245 {
246 if (r < nrows) { pcnt[r] = 0; } else { pstart[r] = n_owned; }
247 });
248 Gpu::DeviceVector<Long> perm(n_owned);
249 auto* pp = perm.data();
250 amrex::ParallelFor(ntrip, [=] AMREX_GPU_DEVICE (Long i) noexcept
251 {
252 if (pr[i] >= row_begin && pr[i] < row_end) {
253 const Long r = pr[i]-row_begin;
254 pp[pstart[r] + Gpu::Atomic::Add(pcnt+r, 1)] = i;
255 }
256 });
257
258 // Sort each row by (column, triplet index) and count its distinct columns
259 Gpu::DeviceVector<Long> nuniq(nrows);
260 auto* pnu = nuniq.data();
261 amrex::ParallelFor(nrows, [=] AMREX_GPU_DEVICE (Long r) noexcept
262 {
263 const Long b = pstart[r], e = pstart[r+1];
264 for (Long k = b+1; k < e; ++k) {
265 const Long t = pp[k];
266 const Long ct = pc[t];
267 Long m = k;
268 while (m > b && (pc[pp[m-1]] > ct || (pc[pp[m-1]] == ct && pp[m-1] > t))) {
269 pp[m] = pp[m-1];
270 --m;
271 }
272 pp[m] = t;
273 }
274 Long u = 0;
275 for (Long k = b; k < e; ++k) {
276 if (k == b || pc[pp[k]] != pc[pp[k-1]]) { ++u; }
277 }
278 pnu[r] = u;
279 });
280
281 // Sum the duplicates
283 csr.row_offset.resize(nrows+1);
284 auto* pro = csr.row_offset.data();
285 const Long nnz = Scan::PrefixSum<Long>(nrows,
286 [=] AMREX_GPU_DEVICE (Long r) -> Long { return pnu[r]; },
287 [=] AMREX_GPU_DEVICE (Long r, Long const& x) { pro[r] = x; },
289 csr.nnz = nnz;
290 csr.col_index.resize(nnz);
291 csr.mat.resize(nnz);
292 auto* pci = csr.col_index.data();
293 auto* pm = csr.mat.data();
294 amrex::ParallelFor(nrows+1, [=] AMREX_GPU_DEVICE (Long r) noexcept
295 {
296 if (r == nrows) { pro[r] = nnz; return; }
297 Long u = pro[r]-1;
298 for (Long k = pstart[r]; k < pstart[r+1]; ++k) {
299 const Long t = pp[k];
300 if (k == pstart[r] || pc[t] != pc[pp[k-1]]) {
301 ++u;
302 pci[u] = pc[t];
303 pm[u] = pv[t];
304 } else {
305 pm[u] += pv[t];
306 }
307 }
308 });
310 rows.clear();
311 cols.clear();
312 vals.clear();
313 mat.define(AlgPartition(rank_offset), std::move(csr), CsrSorted{true});
314}
315
317inline std::map<std::string,int>& dump_counters ()
318{
319 static std::map<std::string,int> counter;
320 return counter;
321}
322
324inline bool dump_pending (std::string const& prefix, int max)
325{
326 return max > 0 && dump_counters()[prefix] < max;
327}
328
330inline int next_dump_index (std::string const& prefix, int max)
331{
332 if (!dump_pending(prefix, max)) { return -1; }
333 return dump_counters()[prefix]++;
334}
335
340template <typename T>
342{
343 const int nprocs = ParallelDescriptor::NProcs(comm);
344 if (nprocs == 1) { return v; }
345#ifdef AMREX_USE_MPI
346 // MPI counts are int (callers check the total with dump_single_file)
347 AMREX_ALWAYS_ASSERT(Long(v.size()) <= Long(std::numeric_limits<int>::max()));
348 int nloc = static_cast<int>(v.size());
349 Vector<int> counts(nprocs), displs(nprocs, 0);
350 MPI_Gather(&nloc, 1, MPI_INT, counts.data(), 1, MPI_INT, 0, comm);
351 Vector<T> g;
352 if (ParallelDescriptor::MyProc(comm) == 0) {
353 Long ntot = 0;
354 for (int p = 0; p < nprocs; ++p) { displs[p] = int(ntot); ntot += counts[p]; }
355 AMREX_ALWAYS_ASSERT(ntot <= Long(std::numeric_limits<int>::max()));
356 g.resize(ntot);
357 }
359 MPI_Gatherv(v.data(), nloc, mt, g.data(), counts.data(), displs.data(), mt, 0, comm);
360 return g;
361#else
362 return v;
363#endif
364}
365
371inline bool dump_single_file (Long total, Long gather_max, MPI_Comm comm)
372{
373 return (ParallelDescriptor::NProcs(comm) == 1) ||
374 (total <= std::min(gather_max, Long(std::numeric_limits<int>::max())));
375}
376
378inline std::ofstream open_dump (std::string const& name)
379{
380 std::ofstream ofs(name);
381 if (!ofs) { amrex::Abort("Cannot open dump file " + name); }
382 ofs << std::setprecision(std::numeric_limits<Real>::max_digits10);
383 return ofs;
384}
385
387inline void check_dump (std::ofstream const& ofs, std::string const& name)
388{
389 if (!ofs) { amrex::Abort("Failed to write dump file " + name); }
390}
391
399inline void write_row_map (std::string const& file, std::string const& title,
400 Vector<std::array<Long,4>> const& info, Vector<Real> const& scaling,
401 Long row_begin, MPI_Comm comm, Long gather_max)
402{
403 const int nprocs = ParallelDescriptor::NProcs(comm);
404 const int myproc = ParallelDescriptor::MyProc(comm);
405 Long nglobal = info.size();
406 ParallelAllReduce::Sum(nglobal, comm);
407
408 Vector<Long> flat(info.size()*4);
409 for (Long r = 0; r < info.size(); ++r) {
410 for (int c = 0; c < 4; ++c) { flat[r*4+c] = info[r][c]; }
411 }
412 auto write = [&] (std::string const& name, std::string const& note, Long first_row,
413 Vector<Long> const& fl, Vector<Real> const& sc)
414 {
415 auto ofs = open_dump(name);
416 ofs << "# " << title << "\n" << note << "# row level i j k scaling\n";
417 for (Long r = 0; r < sc.size(); ++r) {
418 ofs << first_row+r+1 << ' ' << fl[r*4] << ' ' << fl[r*4+1] << ' '
419 << fl[r*4+2] << ' ' << fl[r*4+3] << ' ' << sc[r] << '\n';
420 }
421 check_dump(ofs, name);
422 };
423 if (dump_single_file(4*nglobal, gather_max, comm)) {
424 auto gflat = gather_on_root(flat, comm);
425 auto gscl = gather_on_root(scaling, comm);
426 if (myproc == 0) { write(file, "", 0, gflat, gscl); }
427 } else {
428 write(file + "." + std::to_string(myproc),
429 "# part " + std::to_string(myproc) + " of " + std::to_string(nprocs) +
430 ": rows owned by this rank\n", row_begin, flat, scaling);
431 }
432}
433
442inline void algmg_parse_options (AlgMG<Real>& mg, std::string const& prefix,
443 AlgMGKrylovSolver krylov)
444{
445 ParmParse pp(prefix + ".algmg");
446 int iv = 0;
447 Real rv = 0;
448 Long lv = 0;
449 if (pp.query("verbose", iv)) { mg.setVerbose(iv); }
450 pp.query_enum_case_insensitive("krylov", krylov);
451 mg.setKrylovSolver(krylov);
452 AlgMGSmoother sm{};
453 if (pp.query_enum_case_insensitive("smoother", sm)) { mg.setSmoother(sm); }
454 AlgMGInterpType it{};
455 if (pp.query_enum_case_insensitive("interp_type", it)) { mg.setInterpType(it); }
457 if (pp.query_enum_case_insensitive("bottom_solver", bs)) { mg.setBottomSolver(bs); }
458 if (pp.query("strong_threshold", rv)) { mg.setStrongThreshold(rv); }
459 if (pp.query("max_levels", iv)) { mg.setMaxLevels(iv); }
460 if (pp.query("max_coarse_size", lv)) { mg.setMaxCoarseSize(lv); }
461 if (pp.query("agg_num_levels", iv)) { mg.setAggressiveNumLevels(iv); }
462 if (pp.query("pmax_elmts", iv)) { mg.setPMaxElmts(iv); }
463 if (pp.query("trunc_factor", rv)) { mg.setTruncFactor(rv); }
464 if (pp.query("pre_smooth", iv)) { mg.setPreSmooth(iv); }
465 if (pp.query("post_smooth", iv)) { mg.setPostSmooth(iv); }
466 if (pp.query("cheby_degree", iv)) { mg.setChebyshevDegree(iv); }
467}
468
475inline void write_matrix_market (std::string const& file, OwnedCSR const& csr,
476 Long nglobal, MPI_Comm comm, Long gather_max)
477{
478 const int nprocs = ParallelDescriptor::NProcs(comm);
479 const int myproc = ParallelDescriptor::MyProc(comm);
480 Long nnz_global = csr.nnz();
481 ParallelAllReduce::Sum(nnz_global, comm);
482
483 Vector<Long> rows(csr.nnz());
484 for (Long r = 0; r < csr.nrows; ++r) {
485 for (Long n = csr.row_offset[r]; n < csr.row_offset[r+1]; ++n) { rows[n] = csr.row_begin + r; }
486 }
487 auto write = [&] (std::string const& name, std::string const& note, Vector<Long> const& rr,
488 Vector<Long> const& cc, Vector<Real> const& vv)
489 {
490 auto ofs = open_dump(name);
491 ofs << "%%MatrixMarket matrix coordinate real general\n" << note;
492 ofs << nglobal << ' ' << nglobal << ' ' << vv.size() << '\n';
493 for (Long n = 0; n < vv.size(); ++n) {
494 ofs << rr[n]+1 << ' ' << cc[n]+1 << ' ' << vv[n] << '\n';
495 }
496 check_dump(ofs, name);
497 };
498 if (dump_single_file(nnz_global, gather_max, comm)) {
499 auto grows = gather_on_root(rows, comm);
500 auto gcols = gather_on_root(csr.col_index, comm);
501 auto gvals = gather_on_root(csr.values, comm);
502 if (myproc == 0) { write(file, "", grows, gcols, gvals); }
503 } else {
504 write(file + "." + std::to_string(myproc),
505 "% part " + std::to_string(myproc) + " of " + std::to_string(nprocs) +
506 ": rows owned by this rank\n", rows, csr.col_index, csr.values);
507 }
508}
509
516inline void write_vector_market (std::string const& file, Vector<Real> const& v,
517 Long nglobal, Long row_begin, MPI_Comm comm, Long gather_max)
518{
519 const int nprocs = ParallelDescriptor::NProcs(comm);
520 const int myproc = ParallelDescriptor::MyProc(comm);
521 auto write = [&] (std::string const& name, std::string const& note, Vector<Real> const& x)
522 {
523 auto ofs = open_dump(name);
524 ofs << "%%MatrixMarket matrix array real general\n" << note;
525 ofs << x.size() << " 1\n";
526 for (auto const& xi : x) { ofs << xi << '\n'; }
527 check_dump(ofs, name);
528 };
529 if (dump_single_file(nglobal, gather_max, comm)) {
530 auto g = gather_on_root(v, comm);
531 if (myproc == 0) { write(file, "", g); }
532 } else {
533 write(file + "." + std::to_string(myproc),
534 "% part " + std::to_string(myproc) + " of " + std::to_string(nprocs) +
535 ": rows " + std::to_string(row_begin+1) + " to " +
536 std::to_string(row_begin+v.size()) + " of " + std::to_string(nglobal) + "\n", v);
537 }
538}
539
540}
541
542#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:593
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
while parser_exe_t p
Definition AMReX_Parser_Exe_Body.H:33
Algebraic multigrid solver for SpMatrix / AlgVector systems.
Definition AMReX_AlgMG.H:264
void setAggressiveNumLevels(int n)
Number of levels with aggressive coarsening, starting at the finest. Next setup.
Definition AMReX_AlgMG.H:322
void setChebyshevDegree(int d)
Chebyshev polynomial degree. Next solve.
Definition AMReX_AlgMG.H:298
void setMaxCoarseSize(Long n)
Stop coarsening when a level has at most this many rows. Next setup.
Definition AMReX_AlgMG.H:320
void setPreSmooth(int nu)
Number of pre-smoothing sweeps; negative restores the smoother's default.
Definition AMReX_AlgMG.H:305
void setBottomSolver(BottomSolver bs)
Definition AMReX_AlgMG.H:360
void setPMaxElmts(int n)
Definition AMReX_AlgMG.H:337
void setPostSmooth(int nu)
Number of post-smoothing sweeps; negative restores the smoother's default.
Definition AMReX_AlgMG.H:307
void setInterpType(InterpType it)
Takes effect at the next setup.
Definition AMReX_AlgMG.H:334
void setTruncFactor(T f)
Drop interpolation weights below this fraction of the row maximum. Next setup.
Definition AMReX_AlgMG.H:345
void setMaxLevels(int n)
Definition AMReX_AlgMG.H:318
void setStrongThreshold(T theta)
Definition AMReX_AlgMG.H:315
void setSmoother(Smoother sm)
Takes effect at the next solve; the hierarchy is kept.
Definition AMReX_AlgMG.H:294
void setVerbose(int v)
Definition AMReX_AlgMG.H:284
void setKrylovSolver(KrylovSolver a)
Krylov solver with the V-cycle as preconditioner (see KrylovSolver). Default None.
Definition AMReX_AlgMG.H:347
Definition AMReX_AlgPartition.H:26
size_type size() const noexcept
Definition AMReX_PODVector.H:654
iterator begin() noexcept
Definition AMReX_PODVector.H:680
void resize(size_type a_new_size, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_PODVector.H:734
iterator end() noexcept
Definition AMReX_PODVector.H:684
void clear() noexcept
Definition AMReX_PODVector.H:652
T * data() noexcept
Definition AMReX_PODVector.H:672
Parse Parameters From Command Line and Input Files.
Definition AMReX_ParmParse.H:354
int query_enum_case_insensitive(std::string_view name, T &ref, int ival=FIRST) const
. Query enum value using given name.
Definition AMReX_ParmParse.H:1451
int query(std::string_view name, bool &ref, int ival=FIRST) const
Same as querykth() but searches for the last occurrence of name.
Definition AMReX_ParmParse.cpp:2010
Distributed CSR matrix that manages storage and GPU-friendly partitions.
Definition AMReX_SpMatrix.H:65
CSR< T, container_type > csr_type
Definition AMReX_SpMatrix.H:70
void define(AlgPartition partition, int nnz_per_row)
Allocate storage for a default-constructed matrix with a fixed number of nonzeros per row.
Definition AMReX_SpMatrix.H:917
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:80
amrex_long Long
Definition AMReX_INT.H:30
PODVector< T, ArenaAllocator< T > > DeviceVector
A PODVector that uses the standard memory Arena. Note that the memory might or might not be managed d...
Definition AMReX_GpuContainers.H:24
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
void Sum(Gpu::DeviceVector< T > &v, MPI_Comm comm)
Definition AMReX_GpuParallelReduce.H:37
int NProcs() noexcept
Definition AMReX_ParallelDescriptor.H:255
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:54
__host__ __device__ AMREX_FORCE_INLINE void AddNoRet(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:283
__host__ __device__ AMREX_FORCE_INLINE T Add(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:200
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
A host-to-device copy routine. Note this is just a wrapper around memcpy, so it assumes contiguous st...
Definition AMReX_GpuContainers.H:228
static constexpr DeviceToHost deviceToHost
Definition AMReX_GpuContainers.H:106
static constexpr HostToDevice hostToDevice
Definition AMReX_GpuContainers.H:105
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:329
static constexpr struct amrex::Scan::Type::Exclusive exclusive
static constexpr RetSum retSum
Definition AMReX_Scan.H:34
T PrefixSum(N n, FIN const &fin, FOUT const &fout, TYPE, RetSum a_ret_sum=retSum)
Definition AMReX_Scan.H:815
Definition AMReX_CompositeSystemUtil.H:31
void write_row_map(std::string const &file, std::string const &title, Vector< std::array< Long, 4 > > const &info, Vector< Real > const &scaling, Long row_begin, MPI_Comm comm, Long gather_max)
Write the row map of a composite system: one line per row with the 1-based row, AMR level,...
Definition AMReX_CompositeSystemUtil.H:399
std::string to_sci(double x)
Scientific notation for messages (std::to_string prints 0.000000 for 1e-7).
Definition AMReX_CompositeSystemUtil.H:37
void write_vector_market(std::string const &file, Vector< Real > const &v, Long nglobal, Long row_begin, MPI_Comm comm, Long gather_max)
Write a distributed vector (this rank's rows start at the global row row_begin) as a Matrix Market de...
Definition AMReX_CompositeSystemUtil.H:516
bool dump_single_file(Long total, Long gather_max, MPI_Comm comm)
Whether a dump of total values goes to one file written by rank 0 (always on one rank)....
Definition AMReX_CompositeSystemUtil.H:371
void check_dump(std::ofstream const &ofs, std::string const &name)
Abort if writing a dump file failed.
Definition AMReX_CompositeSystemUtil.H:387
void algmg_parse_options(AlgMG< Real > &mg, std::string const &prefix, AlgMGKrylovSolver krylov)
Configure an AlgMG solver from <prefix>.algmg.*: verbose, krylov (none|bicgstab|gmres|pcg; default kr...
Definition AMReX_CompositeSystemUtil.H:442
bool dump_pending(std::string const &prefix, int max)
Whether a dump with this prefix is still pending (fewer than max written).
Definition AMReX_CompositeSystemUtil.H:324
void write_matrix_market(std::string const &file, OwnedCSR const &csr, Long nglobal, MPI_Comm comm, Long gather_max)
Write a distributed matrix in Matrix Market coordinate format (1-based indices, "general"),...
Definition AMReX_CompositeSystemUtil.H:475
std::ofstream open_dump(std::string const &name)
Open a dump file for writing, aborting on failure.
Definition AMReX_CompositeSystemUtil.H:378
void triplets_to_spmatrix(Gpu::DeviceVector< Long > &rows, Gpu::DeviceVector< Long > &cols, Gpu::DeviceVector< Real > &vals, Long row_begin, Long nrows, Vector< Long > const &rank_offset, MPI_Comm comm, SpMatrix< Real > &mat)
Build an SpMatrix of this rank's rows [row_begin, row_begin+nrows) from (row, column,...
Definition AMReX_CompositeSystemUtil.H:170
Vector< T > gather_on_root(Vector< T > const &v, MPI_Comm comm)
Gather the chunks of a distributed array on rank 0 (ranks in order); other ranks return an empty vect...
Definition AMReX_CompositeSystemUtil.H:341
int next_dump_index(std::string const &prefix, int max)
Index of the next dump for this prefix, or -1 once max have been written.
Definition AMReX_CompositeSystemUtil.H:330
Vector< Triplet > exchange_triplets(Vector< Triplet > &&trips, Vector< Long > const &rank_offset, MPI_Comm comm)
Send each triplet to the rank owning its row (rank p owns rows [rank_offset[p], rank_offset[p+1])) an...
Definition AMReX_CompositeSystemUtil.H:109
std::map< std::string, int > & dump_counters()
Dumps written so far per dump prefix, over all solver objects of the run.
Definition AMReX_CompositeSystemUtil.H:317
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
int MPI_Datatype
Definition AMReX_ccse-mpi.H:53
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
AlgMGInterpType
Definition AMReX_AlgMG.H:220
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
AlgMGBottomSolver
Definition AMReX_AlgMG.H:210
AlgMGKrylovSolver
Definition AMReX_AlgMG.H:216
@ x
Definition AMReX_Orientation.H:14
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
const int[]
Definition AMReX_BLProfiler.cpp:1665
AlgMGSmoother
Definition AMReX_AlgMG.H:229
V< Index > col_index
Definition AMReX_CSR.H:62
V< T > mat
Definition AMReX_CSR.H:61
V< Index > row_offset
Definition AMReX_CSR.H:63
Long nnz
Definition AMReX_CSR.H:64
Sorted CSR means for each row the column indices are sorted.
Definition AMReX_SpMatrix.H:49
Rows owned by this rank in CSR form, columns sorted within each row and duplicates summed.
Definition AMReX_CompositeSystemUtil.H:49
Vector< Long > col_index
global column indices
Definition AMReX_CompositeSystemUtil.H:53
Long nnz() const
Definition AMReX_CompositeSystemUtil.H:56
void define(Long a_row_begin, Long a_nrows, Vector< Triplet > trips)
Definition AMReX_CompositeSystemUtil.H:60
Long nrows
number of rows owned by this rank
Definition AMReX_CompositeSystemUtil.H:51
Vector< Real > values
Definition AMReX_CompositeSystemUtil.H:54
Long row_begin
first global row of this rank
Definition AMReX_CompositeSystemUtil.H:50
Vector< Long > row_offset
size nrows+1
Definition AMReX_CompositeSystemUtil.H:52
void toSpMatrix(SpMatrix< Real > &mat, Vector< Long > const &rank_offset) const
Define an SpMatrix (device memory in GPU builds) with this CSR.
Definition AMReX_CompositeSystemUtil.H:89
(row, column, value) of a matrix entry with global indices
Definition AMReX_CompositeSystemUtil.H:34
Real val
Definition AMReX_CompositeSystemUtil.H:34
Long row
Definition AMReX_CompositeSystemUtil.H:34
Long col
Definition AMReX_CompositeSystemUtil.H:34