22 #include "../config/config.hpp"
29 int AmgXSolver::count = 0;
31 AMGX_resources_handle AmgXSolver::rsrc =
nullptr;
45 const AMGX_MODE amgxMode_,
const bool verbose)
56 const AMGX_MODE amgxMode_,
const bool verbose)
77 mpi_gpu_mode =
"serial";
79 AMGX_SAFE_CALL(AMGX_initialize());
81 AMGX_SAFE_CALL(AMGX_initialize_plugins());
83 AMGX_SAFE_CALL(AMGX_install_signal_handler());
85 MFEM_VERIFY(configSrc != CONFIG_SRC::UNDEFINED,
86 "AmgX configuration is not defined \n");
88 if (configSrc == CONFIG_SRC::EXTERNAL)
90 AMGX_SAFE_CALL(AMGX_config_create_from_file(&cfg, amgx_config.c_str()));
94 AMGX_SAFE_CALL(AMGX_config_create(&cfg, amgx_config.c_str()));
97 AMGX_resources_create_simple(&rsrc, cfg);
98 AMGX_solver_create(&solver, rsrc, precision_mode, cfg);
99 AMGX_matrix_create(&AmgXA, rsrc, precision_mode);
100 AMGX_vector_create(&AmgXP, rsrc, precision_mode);
101 AMGX_vector_create(&AmgXRHS, rsrc, precision_mode);
103 isInitialized =
true;
113 mfem_error(
"This AmgXSolver instance has been initialized on this process.");
117 mpi_gpu_mode =
"mpi-gpu-exclusive";
123 MPI_Comm_dup(comm, &gpuWorld);
124 MPI_Comm_size(gpuWorld, &gpuWorldSize);
125 MPI_Comm_rank(gpuWorld, &myGpuWorldRank);
128 nDevs = 1, devID = 0;
132 isInitialized =
true;
143 mfem_error(
"This AmgXSolver instance has been initialized on this process.");
146 mpi_gpu_mode =
"mpi-teams";
153 char name[MPI_MAX_PROCESSOR_NAME];
154 MPI_Get_processor_name(name, &len);
158 MPI_Comm_rank(comm, &globalcommrank);
161 InitMPIcomms(comm, nDevs);
169 isInitialized =
true;
177 amgx_config = config;
184 amgxMode = amgxMode_;
188 if (amgxMode == AMGX_MODE::PRECONDITIONER)
191 " \"config_version\": 2, \n"
193 " \"solver\": \"AMG\", \n"
194 " \"presweeps\": 1, \n"
195 " \"postsweeps\": 1, \n"
196 " \"interpolator\": \"D2\", \n"
197 " \"max_iters\": 2, \n"
198 " \"convergence\": \"ABSOLUTE\", \n"
202 amgx_config = amgx_config +
",\n"
203 " \"obtain_timings\": 1, \n"
204 " \"monitor_residual\": 1, \n"
205 " \"print_grid_stats\": 1, \n"
206 " \"print_solve_stats\": 1 \n";
210 amgx_config = amgx_config +
"\n";
212 amgx_config = amgx_config +
" }\n" +
"}\n";
214 else if (amgxMode == AMGX_MODE::SOLVER)
217 " \"config_version\": 2, \n"
219 " \"preconditioner\": { \n"
220 " \"solver\": \"AMG\", \n"
221 " \"smoother\": { \n"
222 " \"scope\": \"jacobi\", \n"
223 " \"solver\": \"BLOCK_JACOBI\", \n"
224 " \"relaxation_factor\": 0.7 \n"
226 " \"presweeps\": 1, \n"
227 " \"interpolator\": \"D2\", \n"
228 " \"max_row_sum\" : 0.9, \n"
229 " \"strength_threshold\" : 0.25, \n"
230 " \"max_iters\": 2, \n"
231 " \"scope\": \"amg\", \n"
232 " \"max_levels\": 100, \n"
233 " \"cycle\": \"V\", \n"
234 " \"postsweeps\": 1 \n"
236 " \"solver\": \"PCG\", \n"
237 " \"max_iters\": 100, \n"
238 " \"convergence\": \"RELATIVE_MAX\", \n"
239 " \"scope\": \"main\", \n"
240 " \"tolerance\": 1e-12, \n"
241 " \"norm\": \"L2\" ";
244 amgx_config = amgx_config +
", \n"
245 " \"obtain_timings\": 1, \n"
246 " \"monitor_residual\": 1, \n"
247 " \"print_grid_stats\": 1, \n"
248 " \"print_solve_stats\": 1 \n";
252 amgx_config = amgx_config +
"\n";
254 amgx_config = amgx_config +
" } \n" +
"} \n";
264 void AmgXSolver::InitAmgX()
269 AMGX_SAFE_CALL(AMGX_initialize());
271 AMGX_SAFE_CALL(AMGX_initialize_plugins());
273 AMGX_SAFE_CALL(AMGX_install_signal_handler());
275 AMGX_SAFE_CALL(AMGX_register_print_callback(
276 [](
const char *msg,
int length)->
void
278 int irank; MPI_Comm_rank(MPI_COMM_WORLD, &irank);
282 MFEM_VERIFY(configSrc != CONFIG_SRC::UNDEFINED,
283 "AmgX configuration is not defined \n");
285 if (configSrc == CONFIG_SRC::EXTERNAL)
287 AMGX_SAFE_CALL(AMGX_config_create_from_file(&cfg, amgx_config.c_str()));
291 AMGX_SAFE_CALL(AMGX_config_create(&cfg, amgx_config.c_str()));
295 AMGX_SAFE_CALL(AMGX_config_add_parameters(&cfg,
"exception_handling=1"));
299 if (count == 1) { AMGX_resources_create(&rsrc, cfg, &gpuWorld, 1, &devID); }
302 AMGX_vector_create(&AmgXP, rsrc, precision_mode);
303 AMGX_vector_create(&AmgXRHS, rsrc, precision_mode);
306 AMGX_matrix_create(&AmgXA, rsrc, precision_mode);
309 AMGX_solver_create(&solver, rsrc, precision_mode, cfg);
312 AMGX_config_get_default_number_of_rings(cfg, &ring);
316 void AmgXSolver::InitMPIcomms(
const MPI_Comm &comm,
const int nDevs)
319 MPI_Comm_dup(comm, &globalCpuWorld);
320 MPI_Comm_set_name(globalCpuWorld,
"globalCpuWorld");
323 MPI_Comm_size(globalCpuWorld, &globalSize);
324 MPI_Comm_rank(globalCpuWorld, &myGlobalRank);
327 MPI_Comm_split_type(globalCpuWorld,
328 MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &localCpuWorld);
329 MPI_Comm_set_name(localCpuWorld,
"localCpuWorld");
332 MPI_Comm_size(localCpuWorld, &localSize);
333 MPI_Comm_rank(localCpuWorld, &myLocalRank);
338 MPI_Barrier(globalCpuWorld);
341 MPI_Comm_split(globalCpuWorld, gpuProc, 0, &gpuWorld);
344 if (gpuWorld != MPI_COMM_NULL)
346 MPI_Comm_set_name(gpuWorld,
"gpuWorld");
347 MPI_Comm_size(gpuWorld, &gpuWorldSize);
348 MPI_Comm_rank(gpuWorld, &myGpuWorldRank);
352 gpuWorldSize = MPI_UNDEFINED;
353 myGpuWorldRank = MPI_UNDEFINED;
357 MPI_Comm_split(localCpuWorld, devID, 0, &devWorld);
358 MPI_Comm_set_name(devWorld,
"devWorld");
361 MPI_Comm_size(devWorld, &devWorldSize);
362 MPI_Comm_rank(devWorld, &myDevWorldRank);
364 MPI_Barrier(globalCpuWorld);
368 void AmgXSolver::SetDeviceIDs(
const int nDevs)
371 if (nDevs == localSize)
376 else if (nDevs > localSize)
378 MFEM_WARNING(
"CUDA devices on the node " << nodeName.c_str() <<
379 " are more than the MPI processes launched. Only "<<
380 nDevs <<
" devices will be used.\n");
386 int nBasic = localSize / nDevs,
387 nRemain = localSize % nDevs;
389 if (myLocalRank < (nBasic+1)*nRemain)
391 devID = myLocalRank / (nBasic + 1);
392 if (myLocalRank % (nBasic + 1) == 0) { gpuProc = 0; }
396 devID = (myLocalRank - (nBasic+1)*nRemain) / nBasic + nRemain;
397 if ((myLocalRank - (nBasic+1)*nRemain) % nBasic == 0) { gpuProc = 0; }
402 void AmgXSolver::GatherArray(
const Array<double> &inArr, Array<double> &outArr,
403 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm)
const
406 Array<int> Apart(mpiTeamSz);
407 int locAsz = inArr.Size();
408 MPI_Gather(&locAsz, 1, MPI_INT,
409 Apart.HostWrite(),1, MPI_INT,0,mpiTeamComm);
411 MPI_Barrier(mpiTeamComm);
414 Array<int> Adisp(mpiTeamSz);
415 int myid; MPI_Comm_rank(mpiTeamComm, &myid);
419 for (
int i=1; i<mpiTeamSz; ++i)
421 Adisp[i] = Adisp[i-1] + Apart[i-1];
425 MPI_Gatherv(inArr.HostRead(), inArr.Size(), MPI_DOUBLE,
426 outArr.HostWrite(), Apart.HostRead(), Adisp.HostRead(),
427 MPI_DOUBLE, 0, mpiTeamComm);
430 void AmgXSolver::GatherArray(
const Vector &inArr, Vector &outArr,
431 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm)
const
434 Array<int> Apart(mpiTeamSz);
435 int locAsz = inArr.Size();
436 MPI_Gather(&locAsz, 1, MPI_INT,
437 Apart.HostWrite(),1, MPI_INT,0,mpiTeamComm);
439 MPI_Barrier(mpiTeamComm);
442 Array<int> Adisp(mpiTeamSz);
443 int myid; MPI_Comm_rank(mpiTeamComm, &myid);
447 for (
int i=1; i<mpiTeamSz; ++i)
449 Adisp[i] = Adisp[i-1] + Apart[i-1];
453 MPI_Gatherv(inArr.HostRead(), inArr.Size(), MPI_DOUBLE,
454 outArr.HostWrite(), Apart.HostRead(), Adisp.HostRead(),
455 MPI_DOUBLE, 0, mpiTeamComm);
458 void AmgXSolver::GatherArray(
const Array<int> &inArr, Array<int> &outArr,
459 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm)
const
462 Array<int> Apart(mpiTeamSz);
463 int locAsz = inArr.Size();
464 MPI_Gather(&locAsz, 1, MPI_INT,
465 Apart.GetData(),1, MPI_INT,0,mpiTeamComm);
467 MPI_Barrier(mpiTeamComm);
470 Array<int> Adisp(mpiTeamSz);
471 int myid; MPI_Comm_rank(mpiTeamComm, &myid);
475 for (
int i=1; i<mpiTeamSz; ++i)
477 Adisp[i] = Adisp[i-1] + Apart[i-1];
481 MPI_Gatherv(inArr.HostRead(), inArr.Size(), MPI_INT,
482 outArr.HostWrite(), Apart.HostRead(), Adisp.HostRead(),
483 MPI_INT, 0, mpiTeamComm);
487 void AmgXSolver::GatherArray(
const Array<int64_t> &inArr,
488 Array<int64_t> &outArr,
489 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm)
const
492 Array<int> Apart(mpiTeamSz);
493 int locAsz = inArr.Size();
494 MPI_Gather(&locAsz, 1, MPI_INT,
495 Apart.GetData(),1, MPI_INT,0,mpiTeamComm);
497 MPI_Barrier(mpiTeamComm);
500 Array<int> Adisp(mpiTeamSz);
501 int myid; MPI_Comm_rank(mpiTeamComm, &myid);
505 for (
int i=1; i<mpiTeamSz; ++i)
507 Adisp[i] = Adisp[i-1] + Apart[i-1];
511 MPI_Gatherv(inArr.HostRead(), inArr.Size(), MPI_INT64_T,
512 outArr.HostWrite(), Apart.HostRead(), Adisp.HostRead(),
513 MPI_INT64_T, 0, mpiTeamComm);
515 MPI_Barrier(mpiTeamComm);
518 void AmgXSolver::GatherArray(
const Vector &inArr, Vector &outArr,
519 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm,
520 Array<int> &Apart, Array<int> &Adisp)
const
523 int locAsz = inArr.Size();
524 MPI_Allgather(&locAsz, 1, MPI_INT,
525 Apart.HostWrite(),1, MPI_INT, mpiTeamComm);
527 MPI_Barrier(mpiTeamComm);
531 for (
int i=1; i<mpiTeamSz; ++i)
533 Adisp[i] = Adisp[i-1] + Apart[i-1];
536 MPI_Gatherv(inArr.HostRead(), inArr.Size(), MPI_DOUBLE,
537 outArr.HostWrite(), Apart.HostRead(), Adisp.HostRead(),
538 MPI_DOUBLE, 0, mpiTeamComm);
541 void AmgXSolver::ScatterArray(
const Vector &inArr, Vector &outArr,
542 const int mpiTeamSz,
const MPI_Comm &mpiTeamComm,
543 Array<int> &Apart, Array<int> &Adisp)
const
545 MPI_Scatterv(inArr.HostRead(),Apart.HostRead(),Adisp.HostRead(),
546 MPI_DOUBLE,outArr.HostWrite(),outArr.Size(),
547 MPI_DOUBLE, 0, mpiTeamComm);
551 void AmgXSolver::SetMatrix(
const SparseMatrix &in_A,
const bool update_mat)
553 if (update_mat ==
false)
555 AMGX_matrix_upload_all(AmgXA, in_A.Height(),
556 in_A.NumNonZeroElems(),
560 in_A.ReadData(), NULL);
562 AMGX_solver_setup(solver, AmgXA);
563 AMGX_vector_bind(AmgXP, AmgXA);
564 AMGX_vector_bind(AmgXRHS, AmgXA);
568 AMGX_matrix_replace_coefficients(AmgXA,
570 in_A.NumNonZeroElems(),
571 in_A.ReadData(), NULL);
577 void AmgXSolver::SetMatrix(
const HypreParMatrix &A,
const bool update_mat)
580 #if MFEM_HYPRE_VERSION < 21600
581 mfem_error(
"Hypre version 2.16+ is required when using AmgX \n");
584 hypre_ParCSRMatrix * A_ptr =
585 (hypre_ParCSRMatrix *)const_cast<HypreParMatrix&>(A);
587 hypre_CSRMatrix *A_csr = hypre_MergeDiagAndOffd(A_ptr);
589 Array<double> loc_A(A_csr->data, (
int)A_csr->num_nonzeros);
590 const Array<int> loc_I(A_csr->i, (
int)A_csr->num_rows+1);
593 Array<int64_t> loc_J((
int)A_csr->num_nonzeros);
594 for (
int i=0; i<A_csr->num_nonzeros; ++i)
596 loc_J[i] = A_csr->big_j[i];
600 if (mpi_gpu_mode==
"mpi-gpu-exclusive")
602 return SetMatrixMPIGPUExclusive(A, loc_A, loc_I, loc_J, update_mat);
606 if (mpi_gpu_mode ==
"mpi-teams")
608 return SetMatrixMPITeams(A, loc_A, loc_I, loc_J, update_mat);
611 mfem_error(
"Unsupported MPI_GPU combination \n");
614 void AmgXSolver::SetMatrixMPIGPUExclusive(
const HypreParMatrix &A,
615 const Array<double> &loc_A,
616 const Array<int> &loc_I,
617 const Array<int64_t> &loc_J,
618 const bool update_mat)
621 Array<int64_t> rowPart(gpuWorldSize+1); rowPart = 0.0;
623 int64_t myStart = A.GetRowStarts()[0];
625 MPI_Allgather(&myStart, 1, MPI_INT64_T,
626 rowPart.GetData(),1, MPI_INT64_T
628 MPI_Barrier(gpuWorld);
630 rowPart[gpuWorldSize] = A.M();
632 const int nGlobalRows = A.M();
633 const int local_rows = loc_I.Size()-1;
634 const int num_nnz = loc_I[local_rows];
636 if (update_mat ==
false)
638 AMGX_distribution_handle dist;
639 AMGX_distribution_create(&dist, cfg);
640 AMGX_distribution_set_partition_data(dist, AMGX_DIST_PARTITION_OFFSETS,
643 AMGX_matrix_upload_distributed(AmgXA, nGlobalRows, local_rows,
644 num_nnz, 1, 1, loc_I.Read(),
645 loc_J.Read(), loc_A.Read(),
648 AMGX_distribution_destroy(dist);
650 MPI_Barrier(gpuWorld);
652 AMGX_solver_setup(solver, AmgXA);
654 AMGX_vector_bind(AmgXP, AmgXA);
655 AMGX_vector_bind(AmgXRHS, AmgXA);
659 AMGX_matrix_replace_coefficients(AmgXA,nGlobalRows,num_nnz,loc_A, NULL);
663 void AmgXSolver::SetMatrixMPITeams(
const HypreParMatrix &A,
664 const Array<double> &loc_A,
665 const Array<int> &loc_I,
666 const Array<int64_t> &loc_J,
667 const bool update_mat)
672 Array<int64_t> all_J;
676 int J_allsz(0), all_NNZ(0), nDevRows(0);
677 const int loc_row_len = std::abs(A.RowPart()[1] -
679 const int loc_Jz_sz = loc_J.Size();
680 const int loc_A_sz = loc_A.Size();
682 MPI_Reduce(&loc_row_len, &nDevRows, 1, MPI_INT, MPI_SUM, 0, devWorld);
683 MPI_Reduce(&loc_Jz_sz, &J_allsz, 1, MPI_INT, MPI_SUM, 0, devWorld);
684 MPI_Reduce(&loc_A_sz, &all_NNZ, 1, MPI_INT, MPI_SUM, 0, devWorld);
686 MPI_Barrier(devWorld);
688 if (myDevWorldRank == 0)
690 all_I.SetSize(nDevRows+devWorldSize);
691 all_J.SetSize(J_allsz); all_J = 0.0;
692 all_A.SetSize(all_NNZ);
695 GatherArray(loc_I, all_I, devWorldSize, devWorld);
696 GatherArray(loc_J, all_J, devWorldSize, devWorld);
697 GatherArray(loc_A, all_A, devWorldSize, devWorld);
699 MPI_Barrier(devWorld);
702 int64_t local_rows(0);
704 if (myDevWorldRank == 0)
708 Array<int> z_ind(devWorldSize+1);
710 while (iter < devWorldSize-1)
714 z_ind[counter] = counter;
716 for (
int idx=1; idx<all_I.Size()-1; idx++)
720 z_ind[counter] = idx-1;
724 z_ind[devWorldSize] = all_I.Size()-1;
728 for (
int idx=z_ind[1]+1; idx < z_ind[2]; idx++)
730 all_I[idx] = all_I[idx-1] + (all_I[idx+1] - all_I[idx]);
735 for (
int idx=z_ind[2]; idx < all_I.Size()-1; ++idx)
737 all_I[idx] = all_I[idx+1];
745 z_ind[counter] = counter;
747 for (
int idx=1; idx<all_I.Size()-1; idx++)
751 z_ind[counter] = idx-1;
756 z_ind[devWorldSize] = all_I.Size()-1;
759 for (
int idx=z_ind[1]+1; idx < all_I.Size()-1; idx++)
761 all_I[idx] = all_I[idx-1] + (all_I[idx+1] - all_I[idx]);
763 local_nnz = all_I[all_I.Size()-devWorldSize];
764 local_rows = nDevRows;
768 mat_local_rows = local_rows;
769 Array<int64_t> rowPart;
772 rowPart.SetSize(gpuWorldSize+1); rowPart=0;
774 MPI_Allgather(&local_rows, 1, MPI_INT64_T,
775 &rowPart.GetData()[1], 1, MPI_INT64_T,
777 MPI_Barrier(gpuWorld);
780 for (
int i=1; i<rowPart.Size(); ++i)
782 rowPart[i] += rowPart[i-1];
786 MPI_Barrier(gpuWorld);
788 int nGlobalRows = A.M();
789 if (update_mat ==
false)
791 AMGX_distribution_handle dist;
792 AMGX_distribution_create(&dist, cfg);
793 AMGX_distribution_set_partition_data(dist, AMGX_DIST_PARTITION_OFFSETS,
796 AMGX_matrix_upload_distributed(AmgXA, nGlobalRows, local_rows,
798 1, 1, all_I.ReadWrite(),
803 AMGX_distribution_destroy(dist);
804 MPI_Barrier(gpuWorld);
806 AMGX_solver_setup(solver, AmgXA);
809 AMGX_vector_bind(AmgXP, AmgXA);
810 AMGX_vector_bind(AmgXRHS, AmgXA);
814 AMGX_matrix_replace_coefficients(AmgXA,nGlobalRows,local_nnz,all_A,NULL);
827 dynamic_cast<const SparseMatrix*>(&op))
833 dynamic_cast<const HypreParMatrix*>(&op))
847 dynamic_cast<const SparseMatrix*>(&op))
849 SetMatrix(*Aptr,
true);
853 dynamic_cast<const HypreParMatrix*>(&op))
855 SetMatrix(*Aptr,
true);
871 if (mpi_gpu_mode !=
"mpi-teams")
874 AMGX_vector_upload(AmgXRHS, B.
Size(), 1, B.
Read());
876 if (mpi_gpu_mode !=
"serial")
879 MPI_Barrier(gpuWorld);
883 AMGX_solver_solve(solver,AmgXRHS, AmgXP);
885 AMGX_SOLVE_STATUS status;
886 AMGX_solver_get_status(solver, &status);
887 if (status != AMGX_SOLVE_SUCCESS && amgxMode ==
SOLVER)
889 if (status == AMGX_SOLVE_DIVERGED)
891 mfem_error(
"AmgX solver failed to solve system \n");
899 AMGX_vector_download(AmgXP, X.
Write());
904 Vector all_X(mat_local_rows);
905 Vector all_B(mat_local_rows);
911 GatherArray(X, all_X, devWorldSize, devWorld, Apart_X, Adisp_X);
912 GatherArray(B, all_B, devWorldSize, devWorld, Apart_B, Adisp_B);
913 MPI_Barrier(devWorld);
915 if (gpuWorld != MPI_COMM_NULL)
917 AMGX_vector_upload(AmgXP, all_X.
Size(), 1, all_X.
ReadWrite());
918 AMGX_vector_upload(AmgXRHS, all_B.
Size(), 1, all_B.
ReadWrite());
920 MPI_Barrier(gpuWorld);
922 AMGX_solver_solve(solver,AmgXRHS, AmgXP);
924 AMGX_SOLVE_STATUS status;
925 AMGX_solver_get_status(solver, &status);
926 if (status != AMGX_SOLVE_SUCCESS && amgxMode ==
SOLVER)
928 if (status == AMGX_SOLVE_DIVERGED)
930 mfem_error(
"AmgX solver failed to solve system \n");
938 AMGX_vector_download(AmgXP, all_X.
Write());
941 ScatterArray(all_X, X, devWorldSize, devWorld, Apart_X, Adisp_X);
948 AMGX_solver_get_iterations_number(solver, &getIters);
955 if (! isInitialized || count < 1)
957 mfem_error(
"Error in AmgXSolver::Finalize(). \n"
958 "This AmgXWrapper has not been initialized. \n"
959 "Please initialize it before finalization.\n");
964 if (gpuProc == 0 || mpi_gpu_mode ==
"serial")
968 AMGX_solver_destroy(solver);
971 AMGX_matrix_destroy(AmgXA);
974 AMGX_vector_destroy(AmgXP);
975 AMGX_vector_destroy(AmgXRHS);
980 AMGX_resources_destroy(rsrc);
981 AMGX_SAFE_CALL(AMGX_config_destroy(cfg));
983 AMGX_SAFE_CALL(AMGX_finalize_plugins());
984 AMGX_SAFE_CALL(AMGX_finalize());
988 AMGX_config_destroy(cfg);
992 if (mpi_gpu_mode !=
"serial")
994 MPI_Comm_free(&gpuWorld);
1002 gpuProc = MPI_UNDEFINED;
1003 if (globalCpuWorld != MPI_COMM_NULL)
1005 MPI_Comm_free(&globalCpuWorld);
1006 MPI_Comm_free(&localCpuWorld);
1007 MPI_Comm_free(&devWorld);
1014 isInitialized =
false;
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
int Size() const
Returns the size of the vector.
void InitMPITeams(const MPI_Comm &comm, const int nDevs)
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void ReadParameters(const std::string config, CONFIG_SRC source)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void source(const Vector &x, Vector &f)
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void UpdateOperator(const Operator &op)
virtual void SetOperator(const Operator &op)
void DefaultParameters(const AMGX_MODE amgxMode_, const bool verbose)
int height
Dimension of the output / number of rows in the matrix.
void InitExclusiveGPU(const MPI_Comm &comm)
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Wrapper for hypre's ParCSR matrix class.
AMGX_MODE
Flags to configure AmgXSolver as a solver or preconditioner.
int width
Dimension of the input / number of columns in the matrix.