31Hypre::State Hypre::state = Hypre::State::UNINITIALIZED;
35 if (state != State::INITIALIZED)
37#if MFEM_HYPRE_VERSION >= 21900
47 state = State::INITIALIZED;
55#if defined(HYPRE_USING_GPU) && (MFEM_HYPRE_VERSION >= 23100)
58 MFEM_VERIFY(HYPRE_Initialized(),
"HYPRE must be initialized before"
59 " calling Hypre::InitDevice()");
62 HYPRE_SetMemoryLocation(HYPRE_MEMORY_DEVICE);
63 HYPRE_SetExecutionPolicy(HYPRE_EXEC_DEVICE);
64 HYPRE_DeviceInitialize();
68 HYPRE_SetMemoryLocation(HYPRE_MEMORY_HOST);
69 HYPRE_SetExecutionPolicy(HYPRE_EXEC_HOST);
77 if (state != State::UNINITIALIZED)
79#if MFEM_HYPRE_VERSION >= 21900
83 state = State::UNINITIALIZED;
86void Hypre::SetDefaultOptions()
91#if MFEM_HYPRE_VERSION >= 22100
92#ifdef HYPRE_USING_CUDA
94 HYPRE_SetSpGemmUseCusparse(0);
95#elif defined(HYPRE_USING_HIP)
100 HYPRE_SetSpMVUseVendor(0);
126template<
typename TargetT,
typename SourceT>
127static TargetT *DuplicateAs(
const SourceT *array,
int size,
128 bool cplusplus =
true)
130 TargetT *target_array = cplusplus ? (TargetT*) Memory<TargetT>(size)
131 : mfem_hypre_TAlloc_host(TargetT, size);
132 for (
int i = 0; i < size; i++)
134 target_array[i] = array[i];
157inline void HypreParVector::_SetDataAndSize_()
159 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
160#if !defined(HYPRE_USING_GPU)
162 internal::to_int(hypre_VectorSize(x_loc)));
164 size = internal::to_int(hypre_VectorSize(x_loc));
165 MemoryType mt = (hypre_VectorMemoryLocation(x_loc) == HYPRE_MEMORY_HOST
167 if (hypre_VectorData(x_loc) != NULL)
181 x = hypre_ParVectorCreate(comm,glob_size,col);
182 hypre_ParVectorInitialize(x);
183#if MFEM_HYPRE_VERSION <= 22200
184 hypre_ParVectorSetPartitioningOwner(x,0);
187 hypre_ParVectorSetDataOwner(x,1);
188 hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
198 x = hypre_ParVectorCreate(comm,glob_size,col);
199 hypre_ParVectorSetDataOwner(x,1);
200 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
201 hypre_SeqVectorSetDataOwner(x_loc,0);
202#if MFEM_HYPRE_VERSION <= 22200
203 hypre_ParVectorSetPartitioningOwner(x,0);
206 hypre_VectorData(x_loc) = &tmp;
207#ifdef HYPRE_USING_GPU
208 hypre_VectorMemoryLocation(x_loc) =
209 is_device_ptr ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST;
211 MFEM_CONTRACT_VAR(is_device_ptr);
215 hypre_ParVectorInitialize(x);
217 hypre_VectorData(x_loc) = data_;
227 "the MemoryTypes of 'base' are incompatible with Hypre!");
228 MFEM_ASSERT(offset +
size <= base.
Size(),
229 "the size of 'base' is too small!");
233 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
235#ifdef HYPRE_USING_GPU
242 y.CreateCompatibleVector())
245 hypre_SeqVectorCopy(hypre_ParVectorLocalVector(y.x),
246 hypre_ParVectorLocalVector(x));
252 *
this = std::move(y);
272 x = (hypre_ParVector *) y;
281 hypre_ParVectorInitialize(x);
282#if MFEM_HYPRE_VERSION <= 22200
283 hypre_ParVectorSetPartitioningOwner(x,0);
286 hypre_ParVectorSetDataOwner(x,1);
287 hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
295 result.x = hypre_ParVectorCreate(x -> comm, x -> global_size,
297 hypre_ParVectorInitialize(result.x);
298#if MFEM_HYPRE_VERSION <= 22200
299 hypre_ParVectorSetPartitioningOwner(result.x,0);
301 hypre_ParVectorSetDataOwner(result.x,1);
302 hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(result.x),1);
303 result._SetDataAndSize_();
304 result.own_ParVector = 1;
311 if (own_ParVector) { hypre_ParVectorDestroy(x); }
315 own_ParVector = owner;
320 MFEM_VERIFY(
size > 0,
321 "GlobalVector method can only be called on vectors wherein each "
322 "process owns one or more entries");
323 hypre_Vector *hv = hypre_ParVectorToVectorAll(*
this);
324 Vector *v =
new Vector(hv->data, internal::to_int(hv->size));
326 hypre_SeqVectorSetDataOwner(hv,0);
327 hypre_SeqVectorDestroy(hv);
354 const auto own_tmp = y.own_ParVector;
356 own_ParVector = own_tmp;
357 const auto x_tmp = y.x;
365 hypre_VectorData(hypre_ParVectorLocalVector(x)) = data_;
371 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
372 hypre_VectorData(x_loc) =
374#ifdef HYPRE_USING_GPU
381 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
383#ifdef HYPRE_USING_GPU
390 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
392#ifdef HYPRE_USING_GPU
403 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
404 hypre_VectorData(x_loc) =
406#ifdef HYPRE_USING_GPU
418 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
420#ifdef HYPRE_USING_GPU
432 hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
434#ifdef HYPRE_USING_GPU
442 return hypre_ParVectorSetRandomValues(x,seed);
447 hypre_ParVectorPrint(x, fname.c_str());
454 hypre_ParVectorDestroy(x);
457 x = hypre_ParVectorRead(comm, fname.c_str());
458 own_ParVector =
true;
466 hypre_ParVectorDestroy(x);
473 return hypre_ParVectorInnerProd(*x, *y);
478 return hypre_ParVectorInnerProd(x, y);
492 real_t loc_norm = vec*vec;
499 for (
int i = 0; i < vec.
Size(); i++)
501 sum += pow(fabs(vec(i)),
p);
566template <
typename SrcT,
typename DstT>
575 mfem::forall(capacity, [=] MFEM_HOST_DEVICE (
int i) { dst_p[i] = src_p[i]; });
579void HypreParMatrix::Init()
584 diagOwner = offdOwner = colMapOwner = -1;
594#if MFEM_HYPRE_VERSION >= 21800
595inline decltype(hypre_CSRMatrix::memory_location)
605 decltype(hypre_CSRMatrix::memory_location) ml;
607#if !defined(HYPRE_USING_GPU)
609 ml = HYPRE_MEMORY_HOST;
624 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A);
625 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A);
626 const int num_rows =
NumRows();
627 const int diag_nnz = internal::to_int(diag->num_nonzeros);
628 const int offd_nnz = internal::to_int(offd->num_nonzeros);
629 diag->i =
const_cast<HYPRE_Int*
>(mem_diag.
I.
Read(mc, num_rows+1));
630 diag->j =
const_cast<HYPRE_Int*
>(mem_diag.
J.
Read(mc, diag_nnz));
631 diag->data =
const_cast<real_t*
>(mem_diag.
data.
Read(mc, diag_nnz));
632 offd->i =
const_cast<HYPRE_Int*
>(mem_offd.
I.
Read(mc, num_rows+1));
633 offd->j =
const_cast<HYPRE_Int*
>(mem_offd.
J.
Read(mc, offd_nnz));
634 offd->data =
const_cast<real_t*
>(mem_offd.
data.
Read(mc, offd_nnz));
635#if MFEM_HYPRE_VERSION >= 21800
637 diag->memory_location = ml;
638 offd->memory_location = ml;
644 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A);
645 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A);
646 const int num_rows =
NumRows();
647 const int diag_nnz = internal::to_int(diag->num_nonzeros);
648 const int offd_nnz = internal::to_int(offd->num_nonzeros);
649 diag->i = mem_diag.
I.
ReadWrite(mc, num_rows+1);
652 offd->i = mem_offd.
I.
ReadWrite(mc, num_rows+1);
655#if MFEM_HYPRE_VERSION >= 21800
657 diag->memory_location = ml;
658 offd->memory_location = ml;
662void HypreParMatrix::Write(
MemoryClass mc,
bool set_diag,
bool set_offd)
664 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A);
665 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A);
678#if MFEM_HYPRE_VERSION >= 21800
680 if (set_diag) { diag->memory_location = ml; }
681 if (set_offd) { offd->memory_location = ml; }
699#if MFEM_HYPRE_VERSION >= 21800
700 MemoryType diag_mt = (A->diag->memory_location == HYPRE_MEMORY_HOST
702 MemoryType offd_mt = (A->offd->memory_location == HYPRE_MEMORY_HOST
708 diagOwner = HypreCsrToMem(A->diag, diag_mt,
false, mem_diag);
709 offdOwner = HypreCsrToMem(A->offd, offd_mt,
false, mem_offd);
715 hypre_CSRMatrix *hypre_csr,
730 const int num_rows = csr->
Height();
732 hypre_csr->i =
const_cast<HYPRE_Int*
>(mem_csr.
I.
Read(hypre_mc, num_rows+1));
733 hypre_csr->j =
const_cast<HYPRE_Int*
>(mem_csr.
J.
Read(hypre_mc, nnz));
734 hypre_csr->data =
const_cast<real_t*
>(mem_csr.
data.
Read(hypre_mc, nnz));
737 "invalid state: host ownership for I and J differ!");
739 (mem_csr.data.OwnsHostPtr() ? 2 : 0);
742signed char HypreParMatrix::CopyBoolCSR(Table *bool_csr,
743 MemoryIJData &mem_csr,
744 hypre_CSRMatrix *hypre_csr)
749 CopyMemory(bool_csr->GetIMemory(), mem_csr.I, hypre_mc,
false);
750 CopyMemory(bool_csr->GetJMemory(), mem_csr.J, hypre_mc,
false);
756 const int num_rows = bool_csr->Size();
757 const int nnz = bool_csr->Size_of_connections();
760 for (
int i = 0; i < nnz; i++)
764 hypre_csr->i =
const_cast<HYPRE_Int*
>(mem_csr.I.Read(hypre_mc, num_rows+1));
765 hypre_csr->j =
const_cast<HYPRE_Int*
>(mem_csr.J.Read(hypre_mc, nnz));
766 hypre_csr->data =
const_cast<real_t*
>(mem_csr.data.Read(hypre_mc, nnz));
768 MFEM_ASSERT(mem_csr.I.OwnsHostPtr() == mem_csr.J.OwnsHostPtr(),
769 "invalid state: host ownership for I and J differ!");
770 return (mem_csr.I.OwnsHostPtr() ? 1 : 0) +
771 (mem_csr.data.OwnsHostPtr() ? 2 : 0);
777static void CopyCSR_J(
const int nnz,
const MemoryIJData &mem_csr,
783 mfem::forall(nnz, [=] MFEM_HOST_DEVICE (
int i) { dst_p[i] = src_p[i]; });
788static void SyncBackCSR(SparseMatrix *csr, MemoryIJData &mem_csr)
791 const bool data_shallow =
CanShallowCopy(csr->GetMemoryData(), hypre_mc);
793#if !defined(HYPRE_BIGINT) && defined(MFEM_DEBUG)
794 const bool J_shallow =
CanShallowCopy(csr->GetMemoryJ(), hypre_mc);
795 MFEM_ASSERT(J_shallow == data_shallow,
"unsupported state");
802 csr->GetMemoryJ().Sync(mem_csr.J);
806 CopyCSR_J(csr->GetMemoryJ().Capacity(), mem_csr, csr->GetMemoryJ());
808 csr->GetMemoryData().Sync(mem_csr.data);
813static void SyncBackBoolCSR(Table *bool_csr, MemoryIJData &mem_csr)
816 const bool J_shallow =
CanShallowCopy(bool_csr->GetJMemory(), hypre_mc);
821 bool_csr->GetJMemory().Sync(mem_csr.J);
830static int GetPartitioningArraySize(MPI_Comm comm)
832 if (HYPRE_AssumedPartitionCheck())
839 MPI_Comm_size(comm, &comm_size);
840 return comm_size + 1;
849static bool RowAndColStartsAreEqual(MPI_Comm comm,
const HYPRE_BigInt *rows,
852 const int part_size = GetPartitioningArraySize(comm);
853 bool are_equal =
true;
854 for (
int i = 0; i < part_size; ++i)
856 if (rows[i] != cols[i])
862 MPI_Allreduce(MPI_IN_PLACE, &are_equal, 1, MFEM_MPI_CXX_BOOL, MPI_LAND, comm);
867signed char HypreParMatrix::HypreCsrToMem(hypre_CSRMatrix *h_mat,
872 const int nr1 = internal::to_int(h_mat->num_rows) + 1;
873 const int nnz = internal::to_int(h_mat->num_nonzeros);
874 mem.I.Wrap(h_mat->i, nr1, h_mat_mt, own_ija);
875 mem.J.Wrap(h_mat->j, nnz, h_mat_mt, own_ija);
876 mem.data.Wrap(h_mat->data, nnz, h_mat_mt, own_ija);
882 h_mem.I.New(nr1, hypre_mt);
883 h_mem.I.CopyFrom(mem.I, nr1);
885 h_mem.J.New(nnz, hypre_mt);
886 h_mem.J.CopyFrom(mem.J, nnz);
888 h_mem.data.New(nnz, hypre_mt);
889 h_mem.data.CopyFrom(mem.data, nnz);
898#if MFEM_HYPRE_VERSION < 21400
899 hypre_TFree(h_mat->i);
900#elif MFEM_HYPRE_VERSION < 21800
901 hypre_TFree(h_mat->i, HYPRE_MEMORY_SHARED);
903 hypre_TFree(h_mat->i, h_mat->memory_location);
905 if (h_mat->owns_data)
907#if MFEM_HYPRE_VERSION < 21400
908 hypre_TFree(h_mat->j);
909 hypre_TFree(h_mat->data);
910#elif MFEM_HYPRE_VERSION < 21800
911 hypre_TFree(h_mat->j, HYPRE_MEMORY_SHARED);
912 hypre_TFree(h_mat->data, HYPRE_MEMORY_SHARED);
914 hypre_TFree(h_mat->j, h_mat->memory_location);
915 hypre_TFree(h_mat->data, h_mat->memory_location);
919 h_mat->i = mem.I.ReadWrite(hypre_mc, nr1);
920 h_mat->j = mem.J.ReadWrite(hypre_mc, nnz);
921 h_mat->data = mem.data.ReadWrite(hypre_mc, nnz);
922 h_mat->owns_data = 0;
923#if MFEM_HYPRE_VERSION >= 21800
934 :
Operator(diag->Height(), diag->Width())
937 A = hypre_ParCSRMatrixCreate(comm, glob_size, glob_size, row_starts,
939 hypre_ParCSRMatrixSetDataOwner(A,1);
940#if MFEM_HYPRE_VERSION <= 22200
941 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
942 hypre_ParCSRMatrixSetColStartsOwner(A,0);
945 hypre_CSRMatrixSetDataOwner(A->diag,0);
946 diagOwner = CopyCSR(diag, mem_diag, A->diag,
false);
947 hypre_CSRMatrixSetRownnz(A->diag);
949 hypre_CSRMatrixSetDataOwner(A->offd,1);
950 hypre_CSRMatrixI(A->offd) = mfem_hypre_CTAlloc(HYPRE_Int, diag->
Height()+1);
958 hypre_ParCSRMatrixSetNumNonzeros(A);
962 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
963 SyncBackCSR(diag, mem_diag);
965 hypre_MatvecCommPkgCreate(A);
975 :
Operator(diag->Height(), diag->Width())
978 A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
979 row_starts, col_starts,
981 hypre_ParCSRMatrixSetDataOwner(A,1);
982#if MFEM_HYPRE_VERSION <= 22200
983 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
984 hypre_ParCSRMatrixSetColStartsOwner(A,0);
987 hypre_CSRMatrixSetDataOwner(A->diag,0);
988 diagOwner = CopyCSR(diag, mem_diag, A->diag,
false);
989 hypre_CSRMatrixSetRownnz(A->diag);
991 hypre_CSRMatrixSetDataOwner(A->offd,1);
992 hypre_CSRMatrixI(A->offd) = mfem_hypre_CTAlloc(HYPRE_Int, diag->
Height()+1);
995 hypre_ParCSRMatrixSetNumNonzeros(A);
998 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
1001 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1002 SyncBackCSR(diag, mem_diag);
1005 hypre_MatvecCommPkgCreate(A);
1018 :
Operator(diag->Height(), diag->Width())
1021 A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
1022 row_starts, col_starts,
1025 hypre_ParCSRMatrixSetDataOwner(A,1);
1026#if MFEM_HYPRE_VERSION <= 22200
1027 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
1028 hypre_ParCSRMatrixSetColStartsOwner(A,0);
1031 hypre_CSRMatrixSetDataOwner(A->diag,0);
1032 diagOwner = CopyCSR(diag, mem_diag, A->diag, own_diag_offd);
1033 if (own_diag_offd) {
delete diag; }
1034 hypre_CSRMatrixSetRownnz(A->diag);
1036 hypre_CSRMatrixSetDataOwner(A->offd,0);
1037 offdOwner = CopyCSR(offd, mem_offd, A->offd, own_diag_offd);
1038 if (own_diag_offd) {
delete offd; }
1039 hypre_CSRMatrixSetRownnz(A->offd);
1041 hypre_ParCSRMatrixColMapOffd(A) = cmap;
1045 hypre_ParCSRMatrixSetNumNonzeros(A);
1048 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
1051 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1053 if (!own_diag_offd) { SyncBackCSR(diag, mem_diag); }
1056 hypre_MatvecCommPkgCreate(A);
1066 HYPRE_Int *offd_i, HYPRE_Int *offd_j,
real_t *offd_data,
1071 A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
1072 row_starts, col_starts, offd_num_cols, 0, 0);
1073 hypre_ParCSRMatrixSetDataOwner(A,1);
1074#if MFEM_HYPRE_VERSION <= 22200
1075 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
1076 hypre_ParCSRMatrixSetColStartsOwner(A,0);
1079 HYPRE_Int local_num_rows = hypre_CSRMatrixNumRows(A->diag);
1081 hypre_CSRMatrixSetDataOwner(A->diag, hypre_arrays);
1082 hypre_CSRMatrixI(A->diag) =
diag_i;
1083 hypre_CSRMatrixJ(A->diag) = diag_j;
1084 hypre_CSRMatrixData(A->diag) =
diag_data;
1085 hypre_CSRMatrixNumNonzeros(A->diag) =
diag_i[local_num_rows];
1086#ifdef HYPRE_USING_GPU
1087 hypre_CSRMatrixMemoryLocation(A->diag) = HYPRE_MEMORY_HOST;
1090 hypre_CSRMatrixSetDataOwner(A->offd, hypre_arrays);
1091 hypre_CSRMatrixI(A->offd) = offd_i;
1092 hypre_CSRMatrixJ(A->offd) = offd_j;
1093 hypre_CSRMatrixData(A->offd) = offd_data;
1094 hypre_CSRMatrixNumNonzeros(A->offd) = offd_i[local_num_rows];
1095#ifdef HYPRE_USING_GPU
1096 hypre_CSRMatrixMemoryLocation(A->offd) = HYPRE_MEMORY_HOST;
1099 hypre_ParCSRMatrixColMapOffd(A) = offd_col_map;
1101 colMapOwner = hypre_arrays ? -1 : 1;
1103 hypre_ParCSRMatrixSetNumNonzeros(A);
1106 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
1108 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1111 hypre_MatvecCommPkgCreate(A);
1119 diagOwner = HypreCsrToMem(A->diag, host_mt,
true, mem_diag);
1120 offdOwner = HypreCsrToMem(A->offd, host_mt,
true, mem_offd);
1125 diagOwner = HypreCsrToMem(A->diag, host_mt,
false, mem_diag);
1126 offdOwner = HypreCsrToMem(A->offd, host_mt,
false, mem_offd);
1130 hypre_CSRMatrixSetRownnz(A->diag);
1131 hypre_CSRMatrixSetRownnz(A->offd);
1140 MFEM_ASSERT(sm_a != NULL,
"invalid input");
1141 MFEM_VERIFY(!HYPRE_AssumedPartitionCheck(),
1142 "this method can not be used with assumed partition");
1146 hypre_CSRMatrix *csr_a;
1147 csr_a = hypre_CSRMatrixCreate(sm_a ->
Height(), sm_a ->
Width(),
1148 sm_a -> NumNonZeroElems());
1150 hypre_CSRMatrixSetDataOwner(csr_a,0);
1152 CopyCSR(
const_cast<SparseMatrix*
>(sm_a), mem_a, csr_a,
false);
1153 hypre_CSRMatrixSetRownnz(csr_a);
1157 hypre_ParCSRMatrix *new_A =
1158 hypre_CSRMatrixToParCSRMatrix(comm, csr_a, row_starts, col_starts);
1164 hypre_CSRMatrixI(csr_a) = NULL;
1165 hypre_CSRMatrixDestroy(csr_a);
1168 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
1170 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(new_A));
1173 hypre_MatvecCommPkgCreate(A);
1188 A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
1189 row_starts, col_starts, 0, nnz, 0);
1190 hypre_ParCSRMatrixSetDataOwner(A,1);
1191#if MFEM_HYPRE_VERSION <= 22200
1192 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
1193 hypre_ParCSRMatrixSetColStartsOwner(A,0);
1196 hypre_CSRMatrixSetDataOwner(A->diag,0);
1197 diagOwner = CopyBoolCSR(diag, mem_diag, A->diag);
1198 hypre_CSRMatrixSetRownnz(A->diag);
1200 hypre_CSRMatrixSetDataOwner(A->offd,1);
1201 hypre_CSRMatrixI(A->offd) = mfem_hypre_CTAlloc(HYPRE_Int, diag->
Size()+1);
1204 hypre_ParCSRMatrixSetNumNonzeros(A);
1207 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
1210 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1211 SyncBackBoolCSR(diag, mem_diag);
1214 hypre_MatvecCommPkgCreate(A);
1224 HYPRE_Int *i_diag, HYPRE_Int *j_diag,
1225 HYPRE_Int *i_offd, HYPRE_Int *j_offd,
1228 HYPRE_Int diag_nnz, offd_nnz;
1231 if (HYPRE_AssumedPartitionCheck())
1233 diag_nnz = i_diag[row[1]-row[0]];
1234 offd_nnz = i_offd[row[1]-row[0]];
1236 A = hypre_ParCSRMatrixCreate(comm, row[2], col[2], row, col,
1237 cmap_size, diag_nnz, offd_nnz);
1241 diag_nnz = i_diag[row[
id+1]-row[id]];
1242 offd_nnz = i_offd[row[
id+1]-row[id]];
1244 A = hypre_ParCSRMatrixCreate(comm, row[np], col[np], row, col,
1245 cmap_size, diag_nnz, offd_nnz);
1248 hypre_ParCSRMatrixSetDataOwner(A,1);
1249#if MFEM_HYPRE_VERSION <= 22200
1250 hypre_ParCSRMatrixSetRowStartsOwner(A,0);
1251 hypre_ParCSRMatrixSetColStartsOwner(A,0);
1255 for (HYPRE_Int i = 0; i < diag_nnz; i++)
1257 mem_diag.
data[i] = 1.0;
1261 for (HYPRE_Int i = 0; i < offd_nnz; i++)
1263 mem_offd.
data[i] = 1.0;
1266 hypre_CSRMatrixSetDataOwner(A->diag,0);
1267 hypre_CSRMatrixI(A->diag) = i_diag;
1268 hypre_CSRMatrixJ(A->diag) = j_diag;
1269 hypre_CSRMatrixData(A->diag) = mem_diag.
data;
1270#ifdef HYPRE_USING_GPU
1271 hypre_CSRMatrixMemoryLocation(A->diag) = HYPRE_MEMORY_HOST;
1274 hypre_CSRMatrixSetDataOwner(A->offd,0);
1275 hypre_CSRMatrixI(A->offd) = i_offd;
1276 hypre_CSRMatrixJ(A->offd) = j_offd;
1277 hypre_CSRMatrixData(A->offd) = mem_offd.
data;
1278#ifdef HYPRE_USING_GPU
1279 hypre_CSRMatrixMemoryLocation(A->offd) = HYPRE_MEMORY_HOST;
1282 hypre_ParCSRMatrixColMapOffd(A) = cmap;
1286 hypre_ParCSRMatrixSetNumNonzeros(A);
1291 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1294 hypre_MatvecCommPkgCreate(A);
1300 diagOwner = HypreCsrToMem(A->diag, host_mt,
true, mem_diag);
1301 offdOwner = HypreCsrToMem(A->offd, host_mt,
true, mem_offd);
1304 hypre_CSRMatrixSetRownnz(A->diag);
1305 hypre_CSRMatrixSetRownnz(A->offd);
1323 const int part_size = GetPartitioningArraySize(comm);
1325 if (HYPRE_AssumedPartitionCheck())
1327 my_col_start = cols[0];
1328 my_col_end = cols[1];
1333 MPI_Comm_rank(comm, &myid);
1334 my_col_start = cols[myid];
1335 my_col_end = cols[myid+1];
1339 const bool rows_eq_cols = RowAndColStartsAreEqual(comm, rows, cols);
1343 row_starts = col_starts = mfem_hypre_TAlloc_host(
HYPRE_BigInt, part_size);
1344 for (
int i = 0; i < part_size; i++)
1346 row_starts[i] = rows[i];
1351 row_starts = mfem_hypre_TAlloc_host(
HYPRE_BigInt, part_size);
1352 col_starts = mfem_hypre_TAlloc_host(
HYPRE_BigInt, part_size);
1353 for (
int i = 0; i < part_size; i++)
1355 row_starts[i] = rows[i];
1356 col_starts[i] = cols[i];
1362 HYPRE_Int diag_nnz = 0, offd_nnz = 0, offd_num_cols = 0;
1363 map<HYPRE_BigInt, HYPRE_Int> offd_map;
1364 for (HYPRE_Int j = 0, loc_nnz = I[nrows]; j < loc_nnz; j++)
1367 if (my_col_start <= glob_col && glob_col < my_col_end)
1373 offd_map.insert(pair<const HYPRE_BigInt, HYPRE_Int>(glob_col, -1));
1378 for (
auto it = offd_map.begin(); it != offd_map.end(); ++it)
1380 it->second = offd_num_cols++;
1384 A = hypre_ParCSRMatrixCreate(comm, glob_nrows, glob_ncols,
1385 row_starts, col_starts, offd_num_cols,
1386 diag_nnz, offd_nnz);
1387 hypre_ParCSRMatrixInitialize(A);
1393 HYPRE_Int *
diag_i, *diag_j, *offd_i, *offd_j;
1397 diag_j = A->diag->j;
1399 offd_i = A->offd->i;
1400 offd_j = A->offd->j;
1401 offd_data = A->offd->data;
1402 offd_col_map = A->col_map_offd;
1404 diag_nnz = offd_nnz = 0;
1405 for (HYPRE_Int i = 0, j = 0; i < nrows; i++)
1408 offd_i[i] = offd_nnz;
1409 for (HYPRE_Int j_end = I[i+1]; j < j_end; j++)
1412 if (my_col_start <= glob_col && glob_col < my_col_end)
1414 diag_j[diag_nnz] = glob_col - my_col_start;
1420 offd_j[offd_nnz] = offd_map[glob_col];
1421 offd_data[offd_nnz] = data[j];
1426 diag_i[nrows] = diag_nnz;
1427 offd_i[nrows] = offd_nnz;
1428 for (
auto it = offd_map.begin(); it != offd_map.end(); ++it)
1430 offd_col_map[it->second] = it->first;
1433 hypre_ParCSRMatrixSetNumNonzeros(A);
1437 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
1439#if MFEM_HYPRE_VERSION > 22200
1440 mfem_hypre_TFree_host(row_starts);
1443 mfem_hypre_TFree_host(col_starts);
1446 hypre_MatvecCommPkgCreate(A);
1456 hypre_ParCSRMatrix *Ph =
static_cast<hypre_ParCSRMatrix *
>(P);
1461 A = hypre_ParCSRMatrixCompleteClone(Ph);
1463 hypre_ParCSRMatrixCopy(Ph, A, 1);
1471 hypre_ParCSRMatrixSetNumNonzeros(A);
1473 hypre_MatvecCommPkgCreate(A);
1502 MFEM_ASSERT(diagOwner < 0 && offdOwner < 0 && colMapOwner == -1,
"");
1503 MFEM_ASSERT(diagOwner == offdOwner,
"");
1504 MFEM_ASSERT(ParCSROwner,
"");
1505 hypre_ParCSRMatrix *R = A;
1506#ifdef HYPRE_USING_GPU
1513 ParCSROwner =
false;
1541 colMapOwner = colmap;
1546#if MFEM_HYPRE_VERSION <= 22200
1547 if (!A || hypre_ParCSRMatrixOwnsRowStarts(A) ||
1548 (hypre_ParCSRMatrixRowStarts(A) == hypre_ParCSRMatrixColStarts(A) &&
1549 hypre_ParCSRMatrixOwnsColStarts(A)))
1554 const int row_starts_size = GetPartitioningArraySize(hypre_ParCSRMatrixComm(A));
1556 HYPRE_BigInt *old_row_starts = hypre_ParCSRMatrixRowStarts(A);
1559 for (
int i = 0; i < row_starts_size; i++)
1561 new_row_starts[i] = old_row_starts[i];
1564 hypre_ParCSRMatrixRowStarts(A) = new_row_starts;
1565 hypre_ParCSRMatrixOwnsRowStarts(A) = 1;
1567 if (hypre_ParCSRMatrixColStarts(A) == old_row_starts)
1569 hypre_ParCSRMatrixColStarts(A) = new_row_starts;
1570 hypre_ParCSRMatrixOwnsColStarts(A) = 0;
1577#if MFEM_HYPRE_VERSION <= 22200
1578 if (!A || hypre_ParCSRMatrixOwnsColStarts(A) ||
1579 (hypre_ParCSRMatrixRowStarts(A) == hypre_ParCSRMatrixColStarts(A) &&
1580 hypre_ParCSRMatrixOwnsRowStarts(A)))
1585 const int col_starts_size = GetPartitioningArraySize(hypre_ParCSRMatrixComm(A));
1587 HYPRE_BigInt *old_col_starts = hypre_ParCSRMatrixColStarts(A);
1590 for (
int i = 0; i < col_starts_size; i++)
1592 new_col_starts[i] = old_col_starts[i];
1595 hypre_ParCSRMatrixColStarts(A) = new_col_starts;
1597 if (hypre_ParCSRMatrixRowStarts(A) == old_col_starts)
1599 hypre_ParCSRMatrixRowStarts(A) = new_col_starts;
1600 hypre_ParCSRMatrixOwnsRowStarts(A) = 1;
1601 hypre_ParCSRMatrixOwnsColStarts(A) = 0;
1605 hypre_ParCSRMatrixOwnsColStarts(A) = 1;
1612 const int size =
Height();
1618#if MFEM_HYPRE_VERSION >= 21800
1620 "unexpected HypreParMatrix memory location!");
1622 const HYPRE_Int *A_diag_i = A->diag->i;
1623 const real_t *A_diag_d = A->diag->data;
1625 const HYPRE_Int *A_diag_j = A->diag->j;
1629 diag_hd[i] = A_diag_d[A_diag_i[i]];
1631 A_diag_j[A_diag_i[i]] == i,
1632 "The first entry in each row must be the diagonal one!");
1636static void MakeSparseMatrixWrapper(
int nrows,
int ncols,
1637 HYPRE_Int *I, HYPRE_Int *J,
real_t *data,
1641 SparseMatrix tmp(I, J, data, nrows, ncols,
false,
false,
false);
1644 for (
int i = 0; i <= nrows; i++)
1646 mI[i] = internal::to_int(I[i]);
1648 const int nnz = mI[nrows];
1649 int *mJ = Memory<int>(nnz);
1650 for (
int j = 0; j < nnz; j++)
1652 mJ[j] = internal::to_int(J[j]);
1654 SparseMatrix tmp(mI, mJ, data, nrows, ncols,
true,
false,
false);
1659static void MakeWrapper(
const hypre_CSRMatrix *mat,
1660 const MemoryIJData &mem,
1661 SparseMatrix &wrapper)
1663 const int nrows = internal::to_int(hypre_CSRMatrixNumRows(mat));
1664 const int ncols = internal::to_int(hypre_CSRMatrixNumCols(mat));
1665 const int nnz = internal::to_int(mat->num_nonzeros);
1669 MakeSparseMatrixWrapper(nrows, ncols,
1670 const_cast<HYPRE_Int*
>(I),
1671 const_cast<HYPRE_Int*
>(J),
1672 const_cast<real_t*
>(data),
1678 MakeWrapper(A->diag, mem_diag, diag);
1683 MakeWrapper(A->offd, mem_offd, offd);
1684 cmap = A->col_map_offd;
1688 HYPRE_Int &num_cols)
const
1690 cmap = A->col_map_offd;
1691 num_cols = hypre_CSRMatrixNumCols(A->offd);
1697 hypre_CSRMatrix *hypre_merged = hypre_MergeDiagAndOffd(A);
1701#if MFEM_HYPRE_VERSION >= 21600
1702 hypre_CSRMatrixBigJtoJ(hypre_merged);
1704 MakeSparseMatrixWrapper(
1705 internal::to_int(hypre_merged->num_rows),
1706 internal::to_int(hypre_merged->num_cols),
1713 merged = merged_tmp;
1715 hypre_CSRMatrixDestroy(hypre_merged);
1719 bool interleaved_rows,
1720 bool interleaved_cols)
const
1725 hypre_ParCSRMatrix **hypre_blocks =
new hypre_ParCSRMatrix*[nr * nc];
1727 internal::hypre_ParCSRMatrixSplit(A, nr, nc, hypre_blocks,
1728 interleaved_rows, interleaved_cols);
1731 for (
int i = 0; i < nr; i++)
1733 for (
int j = 0; j < nc; j++)
1739 delete [] hypre_blocks;
1744 hypre_ParCSRMatrix * At;
1745 hypre_ParCSRMatrixTranspose(A, &At, 1);
1746 hypre_ParCSRMatrixSetNumNonzeros(At);
1748 if (!hypre_ParCSRMatrixCommPkg(At)) { hypre_MatvecCommPkgCreate(At); }
1754 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(At));
1760#if MFEM_HYPRE_VERSION >= 21800
1770 hypre_MatvecCommPkgCreate(A);
1773 hypre_ParCSRMatrix *submat;
1776 int local_num_vars = hypre_CSRMatrixNumRows(hypre_ParCSRMatrixDiag(A));
1779#ifdef hypre_IntArrayData
1781 hypre_IntArray *CF_marker;
1783 CF_marker = hypre_IntArrayCreate(local_num_vars);
1784 hypre_IntArrayInitialize_v2(CF_marker, HYPRE_MEMORY_HOST);
1785 hypre_IntArraySetConstantValues(CF_marker, 1);
1790 for (
int j=0; j<indices.
Size(); j++)
1792 if (indices[j] > local_num_vars)
1794 MFEM_WARNING(
"WARNING : " << indices[j] <<
" > " << local_num_vars);
1796#ifdef hypre_IntArrayData
1797 hypre_IntArrayData(CF_marker)[indices[j]] = -1;
1799 CF_marker[indices[j]] = -1;
1804#if (MFEM_HYPRE_VERSION > 22300) || (MFEM_HYPRE_VERSION == 22300 && HYPRE_DEVELOP_NUMBER >=8)
1807 hypre_BoomerAMGCoarseParms(MPI_COMM_WORLD, local_num_vars, 1, NULL,
1808 CF_marker, NULL, cpts_global);
1811 hypre_BoomerAMGCoarseParms(MPI_COMM_WORLD, local_num_vars, 1, NULL,
1812 CF_marker, NULL, &cpts_global);
1816#ifdef hypre_IntArrayData
1817 hypre_ParCSRMatrixExtractSubmatrixFC(A, hypre_IntArrayData(CF_marker),
1818 cpts_global,
"FF", &submat,
1821 hypre_ParCSRMatrixExtractSubmatrixFC(A, CF_marker, cpts_global,
1822 "FF", &submat, threshold);
1825#if (MFEM_HYPRE_VERSION <= 22300) && !(MFEM_HYPRE_VERSION == 22300 && HYPRE_DEVELOP_NUMBER >=8)
1826 mfem_hypre_TFree(cpts_global);
1828#ifdef hypre_IntArrayData
1829 hypre_IntArrayDestroy(CF_marker);
1840#if (MFEM_HYPRE_VERSION == 22500 && HYPRE_DEVELOP_NUMBER >= 1) || \
1841 (MFEM_HYPRE_VERSION > 22500)
1842#ifdef HYPRE_USING_GPU
1845 hypre_ParCSRMatrixLocalTranspose(A);
1853#if (MFEM_HYPRE_VERSION == 22500 && HYPRE_DEVELOP_NUMBER >= 1) || \
1854 (MFEM_HYPRE_VERSION > 22500)
1855#ifdef HYPRE_USING_GPU
1860 hypre_CSRMatrixDestroy(A->diagT);
1865 hypre_CSRMatrixDestroy(A->offdT);
1878 return hypre_ParCSRMatrixMatvec(
a, A, x,
b, y);
1883 MFEM_ASSERT(x.
Size() ==
Width(),
"invalid x.Size() = " << x.
Size()
1884 <<
", expected size = " <<
Width());
1885 MFEM_ASSERT(y.
Size() ==
Height(),
"invalid y.Size() = " << y.
Size()
1886 <<
", expected size = " <<
Height());
1933 hypre_ParCSRMatrixMatvec(
a, A, *X,
b, *Y);
1935 if (!yshallow) { y = *Y; }
1941 MFEM_ASSERT(x.
Size() ==
Height(),
"invalid x.Size() = " << x.
Size()
1942 <<
", expected size = " <<
Height());
1943 MFEM_ASSERT(y.
Size() ==
Width(),
"invalid y.Size() = " << y.
Size()
1944 <<
", expected size = " <<
Width());
1997 hypre_ParCSRMatrixMatvecT(
a, A, *Y,
b, *X);
1999 if (!yshallow) { y = *X; }
2005 return hypre_ParCSRMatrixMatvec(
a, A, (hypre_ParVector *) x,
b,
2006 (hypre_ParVector *) y);
2015 return hypre_ParCSRMatrixMatvecT(
a, A, x,
b, y);
2021 MFEM_ASSERT(x.
Size() ==
Width(),
"invalid x.Size() = " << x.
Size()
2022 <<
", expected size = " <<
Width());
2023 MFEM_ASSERT(y.
Size() ==
Height(),
"invalid y.Size() = " << y.
Size()
2024 <<
", expected size = " <<
Height());
2030 internal::hypre_ParCSRMatrixAbsMatvec(A,
a,
const_cast<real_t*
>(x_data),
2038 MFEM_ASSERT(x.
Size() ==
Height(),
"invalid x.Size() = " << x.
Size()
2039 <<
", expected size = " <<
Height());
2040 MFEM_ASSERT(y.
Size() ==
Width(),
"invalid y.Size() = " << y.
Size()
2041 <<
", expected size = " <<
Width());
2047 internal::hypre_ParCSRMatrixAbsMatvecT(A,
a,
const_cast<real_t*
>(x_data),
2055 const bool assumed_partition = HYPRE_AssumedPartitionCheck();
2056 const bool row_starts_given = (row_starts != NULL);
2057 if (!row_starts_given)
2059 row_starts = hypre_ParCSRMatrixRowStarts(A);
2060 MFEM_VERIFY(D.
Height() == hypre_CSRMatrixNumRows(A->diag),
2061 "the matrix D is NOT compatible with the row starts of"
2062 " this HypreParMatrix, row_starts must be given.");
2067 if (assumed_partition)
2073 MPI_Comm_rank(
GetComm(), &offset);
2075 int local_num_rows = row_starts[offset+1]-row_starts[offset];
2076 MFEM_VERIFY(local_num_rows == D.
Height(),
"the number of rows in D is "
2077 " not compatible with the given row_starts");
2084 if (assumed_partition)
2087 if (row_starts_given)
2089 global_num_rows = row_starts[2];
2096 global_num_rows = hypre_ParCSRMatrixGlobalNumRows(A);
2101 MPI_Comm_size(
GetComm(), &part_size);
2102 global_num_rows = row_starts[part_size];
2106 HYPRE_BigInt *col_starts = hypre_ParCSRMatrixColStarts(A);
2112 GetOffd(A_offd, col_map_offd);
2122 DuplicateAs<HYPRE_BigInt>(row_starts, part_size,
false);
2124 (row_starts == col_starts ? new_row_starts :
2125 DuplicateAs<HYPRE_BigInt>(col_starts, part_size,
false));
2127 DuplicateAs<HYPRE_BigInt>(col_map_offd, A_offd.
Width());
2131 const bool own_diag_offd =
true;
2136 global_num_rows, hypre_ParCSRMatrixGlobalNumCols(A),
2137 new_row_starts, new_col_starts,
2138 DA_diag, DA_offd, new_col_map_offd,
2141#if MFEM_HYPRE_VERSION <= 22200
2143 hypre_ParCSRMatrixSetRowStartsOwner(DA->A, 1);
2144 hypre_ParCSRMatrixSetColStartsOwner(DA->A, 1);
2146 mfem_hypre_TFree_host(new_row_starts);
2147 mfem_hypre_TFree_host(new_col_starts);
2149 DA->colMapOwner = 1;
2156 if (hypre_CSRMatrixNumRows(A->diag) != hypre_CSRMatrixNumRows(A->offd))
2161 if (hypre_CSRMatrixNumRows(A->diag) != diag.
Size())
2163 mfem_error(
"Note the Vector diag is not of compatible dimensions with A\n");
2170 real_t *Adiag_data = hypre_CSRMatrixData(A->diag);
2171 HYPRE_Int *Adiag_i = hypre_CSRMatrixI(A->diag);
2173 real_t *Aoffd_data = hypre_CSRMatrixData(A->offd);
2174 HYPRE_Int *Aoffd_i = hypre_CSRMatrixI(A->offd);
2177 for (
int i(0); i < size; ++i)
2180 for (jj = Adiag_i[i]; jj < Adiag_i[i+1]; ++jj)
2182 Adiag_data[jj] *= val;
2184 for (jj = Aoffd_i[i]; jj < Aoffd_i[i+1]; ++jj)
2186 Aoffd_data[jj] *= val;
2195 if (hypre_CSRMatrixNumRows(A->diag) != hypre_CSRMatrixNumRows(A->offd))
2200 if (hypre_CSRMatrixNumRows(A->diag) != diag.
Size())
2202 mfem_error(
"Note the Vector diag is not of compatible dimensions with A\n");
2209 real_t *Adiag_data = hypre_CSRMatrixData(A->diag);
2210 HYPRE_Int *Adiag_i = hypre_CSRMatrixI(A->diag);
2213 real_t *Aoffd_data = hypre_CSRMatrixData(A->offd);
2214 HYPRE_Int *Aoffd_i = hypre_CSRMatrixI(A->offd);
2217 for (
int i(0); i < size; ++i)
2222 mfem_error(
"HypreParMatrix::InvDiagScale : Division by 0");
2226 for (jj = Adiag_i[i]; jj < Adiag_i[i+1]; ++jj)
2228 Adiag_data[jj] *= val;
2230 for (jj = Aoffd_i[i]; jj < Aoffd_i[i+1]; ++jj)
2232 Aoffd_data[jj] *= val;
2241 if (hypre_CSRMatrixNumRows(A->diag) != hypre_CSRMatrixNumRows(A->offd))
2248 HYPRE_Int size=hypre_CSRMatrixNumRows(A->diag);
2251 real_t *Adiag_data = hypre_CSRMatrixData(A->diag);
2252 HYPRE_Int *Adiag_i = hypre_CSRMatrixI(A->diag);
2253 for (jj = 0; jj < Adiag_i[size]; ++jj)
2255 Adiag_data[jj] *= s;
2258 real_t *Aoffd_data = hypre_CSRMatrixData(A->offd);
2259 HYPRE_Int *Aoffd_i = hypre_CSRMatrixI(A->offd);
2260 for (jj = 0; jj < Aoffd_i[size]; ++jj)
2262 Aoffd_data[jj] *= s;
2268static void get_sorted_rows_cols(
const Array<int> &rows_cols,
2274 for (
int i = 0; i < rows_cols.
Size(); i++)
2276 hypre_sorted[i] = rows_cols[i];
2277 if (i && rows_cols[i-1] > rows_cols[i]) { sorted =
false; }
2279 if (!sorted) { hypre_sorted.
Sort(); }
2287 hypre_CSRMatrix * csr_A;
2288 hypre_CSRMatrix * csr_A_wo_z;
2289 hypre_ParCSRMatrix * parcsr_A_ptr;
2294 comm = hypre_ParCSRMatrixComm(A);
2296 ierr += hypre_ParCSRMatrixGetLocalRange(A,
2297 &row_start,&row_end,
2298 &col_start,&col_end );
2300 row_starts = hypre_ParCSRMatrixRowStarts(A);
2301 col_starts = hypre_ParCSRMatrixColStarts(A);
2303#if MFEM_HYPRE_VERSION <= 22200
2304 bool old_owns_row = hypre_ParCSRMatrixOwnsRowStarts(A);
2305 bool old_owns_col = hypre_ParCSRMatrixOwnsColStarts(A);
2307 HYPRE_BigInt global_num_rows = hypre_ParCSRMatrixGlobalNumRows(A);
2308 HYPRE_BigInt global_num_cols = hypre_ParCSRMatrixGlobalNumCols(A);
2309 parcsr_A_ptr = hypre_ParCSRMatrixCreate(comm, global_num_rows,
2311 row_starts, col_starts,
2313#if MFEM_HYPRE_VERSION <= 22200
2314 hypre_ParCSRMatrixOwnsRowStarts(parcsr_A_ptr) = old_owns_row;
2315 hypre_ParCSRMatrixOwnsColStarts(parcsr_A_ptr) = old_owns_col;
2316 hypre_ParCSRMatrixOwnsRowStarts(A) = 0;
2317 hypre_ParCSRMatrixOwnsColStarts(A) = 0;
2320 csr_A = hypre_MergeDiagAndOffd(A);
2326 csr_A_wo_z = hypre_CSRMatrixDeleteZeros(csr_A,threshold);
2330 if (csr_A_wo_z == NULL)
2336 ierr += hypre_CSRMatrixDestroy(csr_A);
2342 ierr += hypre_GenerateDiagAndOffd(csr_A_wo_z,parcsr_A_ptr,
2345 ierr += hypre_CSRMatrixDestroy(csr_A_wo_z);
2347 MFEM_VERIFY(ierr == 0,
"");
2351 hypre_ParCSRMatrixSetNumNonzeros(A);
2353 if (RowAndColStartsAreEqual(comm, row_starts, col_starts))
2355 hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
2357 if (!hypre_ParCSRMatrixCommPkg(A)) { hypre_MatvecCommPkgCreate(A); }
2364 HYPRE_Int old_err = hypre_error_flag;
2365 hypre_error_flag = 0;
2367#if MFEM_HYPRE_VERSION < 21400
2372 HYPRE_Int *diag_I = A->diag->i, *offd_I = A->offd->i;
2373 real_t *diag_d = A->diag->data, *offd_d = A->offd->data;
2374 HYPRE_Int local_num_rows = A->diag->num_rows;
2375 real_t max_l2_row_norm = 0.0;
2377 for (HYPRE_Int r = 0; r < local_num_rows; r++)
2382 l2_row_norm = std::hypot(l2_row_norm, row.
Norml2());
2383 max_l2_row_norm = std::max(max_l2_row_norm, l2_row_norm);
2385 real_t loc_max_l2_row_norm = max_l2_row_norm;
2386 MPI_Allreduce(&loc_max_l2_row_norm, &max_l2_row_norm, 1,
2389 threshold = tol * max_l2_row_norm;
2394#elif MFEM_HYPRE_VERSION < 21800
2396 HYPRE_Int err_flag = hypre_ParCSRMatrixDropSmallEntries(A, tol);
2397 MFEM_VERIFY(!err_flag,
"error encountered: error code = " << err_flag);
2401 HYPRE_Int err_flag = hypre_ParCSRMatrixDropSmallEntries(A, tol, 2);
2402 MFEM_VERIFY(!err_flag,
"error encountered: error code = " << err_flag);
2406 hypre_error_flag = old_err;
2414 get_sorted_rows_cols(rows_cols, rc_sorted);
2416 internal::hypre_ParCSRMatrixEliminateAXB(
2423 get_sorted_rows_cols(rows_cols, rc_sorted);
2425 hypre_ParCSRMatrix* Ae;
2427 internal::hypre_ParCSRMatrixEliminateAAe(
2437 get_sorted_rows_cols(cols, rc_sorted);
2439 hypre_ParCSRMatrix* Ae;
2441 internal::hypre_ParCSRMatrixEliminateAAe(
2442 A, &Ae, rc_sorted.
Size(), rc_sorted.
GetData(), 1);
2450 if (rows.
Size() > 0)
2453 get_sorted_rows_cols(rows, r_sorted);
2455 internal::hypre_ParCSRMatrixEliminateRows(A, r_sorted.
Size(),
2466 Ae.
Mult(-1.0, x, 1.0,
b);
2470 if (ess_dof_list.
Size() == 0) {
return; }
2473 hypre_CSRMatrix *A_diag = hypre_ParCSRMatrixDiag(A);
2474 real_t *data = hypre_CSRMatrixData(A_diag);
2475 HYPRE_Int *I = hypre_CSRMatrixI(A_diag);
2477 HYPRE_Int *J = hypre_CSRMatrixJ(A_diag);
2478 hypre_CSRMatrix *A_offd = hypre_ParCSRMatrixOffd(A);
2479 HYPRE_Int *I_offd = hypre_CSRMatrixI(A_offd);
2480 real_t *data_offd = hypre_CSRMatrixData(A_offd);
2487 for (
int i = 0; i < ess_dof_list.
Size(); i++)
2489 int r = ess_dof_list[i];
2490 b(r) = data[I[r]] * x(r);
2492 MFEM_ASSERT(I[r] < I[r+1],
"empty row found!");
2498 MFEM_ABORT(
"the diagonal entry must be the first entry in the row!");
2500 for (
int j = I[r]+1; j < I[r+1]; j++)
2504 MFEM_ABORT(
"all off-diagonal entries must be zero!");
2507 for (
int j = I_offd[r]; j < I_offd[r+1]; j++)
2509 if (data_offd[j] != 0.0)
2511 MFEM_ABORT(
"all off-diagonal entries must be zero!");
2522 hypre_ParCSRMatrix *A_hypre = *
this;
2525 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A_hypre);
2526 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A_hypre);
2528 HYPRE_Int diag_nrows = hypre_CSRMatrixNumRows(diag);
2529 HYPRE_Int offd_ncols = hypre_CSRMatrixNumCols(offd);
2531 const int n_ess_dofs = ess_dofs.
Size();
2532 const auto ess_dofs_d = ess_dofs.
GetMemory().Read(
2537 hypre_ParCSRCommHandle *comm_handle;
2538 HYPRE_Int *int_buf_data, *eliminate_row, *eliminate_col;
2540 eliminate_row = mfem_hypre_CTAlloc(HYPRE_Int, diag_nrows);
2541 eliminate_col = mfem_hypre_CTAlloc(HYPRE_Int, offd_ncols);
2544 hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
2547 hypre_MatvecCommPkgCreate(A_hypre);
2548 comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
2554 eliminate_row[i] = 0;
2558 eliminate_row[ess_dofs_d[i]] = 1;
2564 HYPRE_Int num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg);
2565 HYPRE_Int int_buf_sz = hypre_ParCSRCommPkgSendMapStart(comm_pkg, num_sends);
2566 int_buf_data = mfem_hypre_CTAlloc(HYPRE_Int, int_buf_sz);
2568 HYPRE_Int *send_map_elmts;
2569#if defined(HYPRE_USING_GPU)
2572 hypre_ParCSRCommPkgCopySendMapElmtsToDevice(comm_pkg);
2573 send_map_elmts = hypre_ParCSRCommPkgDeviceSendMapElmts(comm_pkg);
2578 send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg);
2582 int k = send_map_elmts[i];
2583 int_buf_data[i] = eliminate_row[k];
2586#if defined(HYPRE_USING_GPU)
2589#if defined(HYPRE_WITH_GPU_AWARE_MPI) || defined(HYPRE_USING_GPU_AWARE_MPI)
2593#if MFEM_HYPRE_VERSION >= 23300
2594 if (hypre_GetGpuAwareMPI())
2602 comm_handle = hypre_ParCSRCommHandleCreate_v2(
2603 11, comm_pkg, HYPRE_MEMORY_DEVICE, int_buf_data,
2604 HYPRE_MEMORY_DEVICE, eliminate_col);
2609 comm_handle = hypre_ParCSRCommHandleCreate(
2610 11, comm_pkg, int_buf_data, eliminate_col );
2616 const auto I = diag->i;
2617 const auto J = diag->j;
2618 auto data = diag->data;
2622 const int idof = ess_dofs_d[i];
2623 for (
auto j=I[idof]; j<I[idof+1]; ++j)
2625 const auto jdof = J[j];
2641 for (
auto k=I[jdof]; k<I[jdof+1]; ++k)
2656 const auto I = offd->i;
2657 auto data = offd->data;
2660 const int idof = ess_dofs_d[i];
2661 for (
auto j=I[idof]; j<I[idof+1]; ++j)
2669 hypre_ParCSRCommHandleDestroy(comm_handle);
2670 mfem_hypre_TFree(int_buf_data);
2671 mfem_hypre_TFree(eliminate_row);
2675 const int nrows_offd = hypre_CSRMatrixNumRows(offd);
2676 const auto I = offd->i;
2677 const auto J = offd->j;
2678 auto data = offd->data;
2681 for (
auto j=I[i]; j<I[i+1]; ++j)
2683 data[j] *= 1 - eliminate_col[J[j]];
2688 mfem_hypre_TFree(eliminate_col);
2692 HYPRE_Int offj)
const
2695 hypre_ParCSRMatrixPrintIJ(A, offi, offj, fname.c_str());
2699void HypreParMatrix::Read(MPI_Comm comm,
const std::string &fname)
2701 HYPRE_ParCSRMatrix A_parcsr;
2702 HYPRE_Int base_i, base_j;
2703 hypre_ParCSRMatrixReadIJ(comm, fname.c_str(), &base_i, &base_j, &A_parcsr);
2707 hypre_ParCSRMatrixSetNumNonzeros(A);
2708 if (!hypre_ParCSRMatrixCommPkg(A)) { hypre_MatvecCommPkgCreate(A); }
2713 HYPRE_IJMatrix A_ij;
2714 HYPRE_IJMatrixRead(fname.c_str(), comm, 5555, &A_ij);
2716 HYPRE_ParCSRMatrix A_parcsr;
2717 HYPRE_IJMatrixGetObject(A_ij, (
void**) &A_parcsr);
2721 hypre_ParCSRMatrixSetNumNonzeros(A);
2722 if (!hypre_ParCSRMatrixCommPkg(A)) { hypre_MatvecCommPkgCreate(A); }
2727 hypre_ParCSRCommPkg *comm_pkg = A->comm_pkg;
2728 MPI_Comm comm = A->comm;
2730 const int tag = 46801;
2732 MPI_Comm_rank(comm, &myid);
2733 MPI_Comm_size(comm, &nproc);
2737 MPI_Recv(&c, 1, MPI_CHAR, myid-1, tag, comm, MPI_STATUS_IGNORE);
2741 os <<
"\nHypreParMatrix: hypre_ParCSRCommPkg:\n";
2743 os <<
"Rank " << myid <<
":\n"
2744 " number of sends = " << comm_pkg->num_sends <<
2745 " (" <<
sizeof(
real_t)*comm_pkg->send_map_starts[comm_pkg->num_sends] <<
2747 " number of recvs = " << comm_pkg->num_recvs <<
2748 " (" <<
sizeof(
real_t)*comm_pkg->recv_vec_starts[comm_pkg->num_recvs] <<
2750 if (myid != nproc-1)
2753 MPI_Send(&c, 1, MPI_CHAR, myid+1, tag, comm);
2766 os <<
"global number of rows : " << A->global_num_rows <<
'\n'
2767 <<
"global number of columns : " << A->global_num_cols <<
'\n'
2768 <<
"first row index : " << A->first_row_index <<
'\n'
2769 <<
" last row index : " << A->last_row_index <<
'\n'
2770 <<
"first col diag : " << A->first_col_diag <<
'\n'
2771 <<
" last col diag : " << A->last_col_diag <<
'\n'
2772 <<
"number of nonzeros : " << A->num_nonzeros <<
'\n';
2774 hypre_CSRMatrix *csr = A->diag;
2775 const char *csr_name =
"diag";
2776 for (
int m = 0; m < 2; m++)
2778 auto csr_nnz = csr->i[csr->num_rows];
2779 os << csr_name <<
" num rows : " << csr->num_rows <<
'\n'
2780 << csr_name <<
" num cols : " << csr->num_cols <<
'\n'
2781 << csr_name <<
" num nnz : " << csr->num_nonzeros <<
'\n'
2782 << csr_name <<
" i last : " << csr_nnz
2783 << (csr_nnz == csr->num_nonzeros ?
2784 " [good]" :
" [** BAD **]") <<
'\n';
2786 os << csr_name <<
" i hash : " << hf.
GetHash() <<
'\n';
2787 os << csr_name <<
" j hash : ";
2788 if (csr->j ==
nullptr)
2797#if MFEM_HYPRE_VERSION >= 21600
2798 os << csr_name <<
" big j hash : ";
2799 if (csr->big_j ==
nullptr)
2809 os << csr_name <<
" data hash : ";
2810 if (csr->data ==
nullptr)
2824 hf.
AppendInts(A->col_map_offd, A->offd->num_cols);
2825 os <<
"col map offd hash : " << hf.
GetHash() <<
'\n';
2832#if MFEM_HYPRE_VERSION >= 21900
2834 const int ierr = hypre_ParCSRMatrixNormFro(A, &norm_fro);
2835 MFEM_VERIFY(ierr == 0,
"");
2842 Vector Avec_diag(A->diag->data, A->diag->num_nonzeros);
2844 Vector Avec_offd(A->offd->data, A->offd->num_nonzeros);
2847 MPI_SUM, hypre_ParCSRMatrixComm(A));
2848 norm_fro = sqrt(normsqr_fro);
2857 HYPRE_BigInt *A_col_map_offd = hypre_ParCSRMatrixColMapOffd(A);
2858 int size = hypre_CSRMatrixNumCols(hypre_ParCSRMatrixOffd(A));
2862void HypreParMatrix::Destroy()
2864 if ( X != NULL ) {
delete X; }
2865 if ( Y != NULL ) {
delete Y; }
2869 if (A == NULL) {
return; }
2871#ifdef HYPRE_USING_GPU
2872 if (
HypreUsingGPU() && ParCSROwner && (diagOwner < 0 || offdOwner < 0))
2880 MFEM_VERIFY(!(diagOwner < 0 && offdOwner < 0) || diagOwner == offdOwner,
2883 MemoryClass mc = (diagOwner == -1 || offdOwner == -1) ?
2885 Write(mc, diagOwner < 0, offdOwner < 0);
2886 if (diagOwner == -1)
2889 mfem_hypre_TFree_host(hypre_CSRMatrixI(A->diag));
2890 if (hypre_CSRMatrixOwnsData(A->diag))
2892 mfem_hypre_TFree_host(hypre_CSRMatrixJ(A->diag));
2893 mfem_hypre_TFree_host(hypre_CSRMatrixData(A->diag));
2895#if MFEM_HYPRE_VERSION >= 21800
2899 if (offdOwner == -1)
2902 mfem_hypre_TFree_host(hypre_CSRMatrixI(A->offd));
2903 if (hypre_CSRMatrixOwnsData(A->offd))
2905 mfem_hypre_TFree_host(hypre_CSRMatrixJ(A->offd));
2906 mfem_hypre_TFree_host(hypre_CSRMatrixData(A->offd));
2908#if MFEM_HYPRE_VERSION >= 21800
2920 hypre_CSRMatrixI(A->diag) = NULL;
2921 hypre_CSRMatrixJ(A->diag) = NULL;
2922 hypre_CSRMatrixData(A->diag) = NULL;
2929 hypre_CSRMatrixI(A->offd) = NULL;
2930 hypre_CSRMatrixJ(A->offd) = NULL;
2931 hypre_CSRMatrixData(A->offd) = NULL;
2933 if (colMapOwner >= 0)
2935 if (colMapOwner & 1)
2939 hypre_ParCSRMatrixColMapOffd(A) = NULL;
2944 hypre_ParCSRMatrixDestroy(A);
2953 MFEM_CONTRACT_VAR(own_j);
2954 MFEM_ASSERT(own_i == own_j,
"Inconsistent ownership");
2968#if MFEM_HYPRE_VERSION >= 21800
2977 hypre_ParCSRMatrix *C_hypre;
2978 hypre_ParcsrBdiagInvScal(*A, blocksize, &C_hypre);
2979 hypre_ParCSRMatrixDropSmallEntries(C_hypre, 1e-15, 1);
2989 hypre_ParVector *d_hypre;
2990 hypre_ParvecBdiagInvScal(b_Hypre, blocksize, &d_hypre, *A);
2998#if MFEM_HYPRE_VERSION < 21400
3003 hypre_ParCSRMatrix *C_hypre =
3006 MFEM_VERIFY(C_hypre,
"error in hypre_ParCSRMatrixAdd");
3008 if (!hypre_ParCSRMatrixCommPkg(C_hypre)) { hypre_MatvecCommPkgCreate(C_hypre); }
3019 hypre_ParCSRMatrix * C = internal::hypre_ParCSRMatrixAdd(*A,*B);
3021 if (!hypre_ParCSRMatrixCommPkg(C)) { hypre_MatvecCommPkgCreate(C); }
3029 real_t beta,
const HypreParMatrix &B)
3031 hypre_ParCSRMatrix *C;
3032#if MFEM_HYPRE_VERSION <= 22000
3033 hypre_ParcsrAdd(
alpha, A, beta, B, &C);
3035 hypre_ParCSRMatrixAdd(
alpha, A, beta, B, &C);
3037 if (!hypre_ParCSRMatrixCommPkg(C)) { hypre_MatvecCommPkgCreate(C); }
3039 return new HypreParMatrix(C);
3042HypreParMatrix *
ParAdd(
const HypreParMatrix *A,
const HypreParMatrix *B)
3044 hypre_ParCSRMatrix *C;
3045#if MFEM_HYPRE_VERSION <= 22000
3046 hypre_ParcsrAdd(1.0, *A, 1.0, *B, &C);
3048 hypre_ParCSRMatrixAdd(1.0, *A, 1.0, *B, &C);
3050 if (!hypre_ParCSRMatrixCommPkg(C)) { hypre_MatvecCommPkgCreate(C); }
3052 return new HypreParMatrix(C);
3060 hypre_ParCSRMatrix * ab;
3061#ifdef HYPRE_USING_GPU
3064 ab = hypre_ParCSRMatMat(*A, *B);
3069 ab = hypre_ParMatmul(*A,*B);
3071 hypre_ParCSRMatrixSetNumNonzeros(ab);
3073 if (!hypre_ParCSRMatrixCommPkg(ab)) { hypre_MatvecCommPkgCreate(ab); }
3085 hypre_ParCSRMatrix * rap;
3087#ifdef HYPRE_USING_GPU
3096 hypre_ParCSRMatrix *Q = hypre_ParCSRMatMat(*A,*P);
3097 const bool keepTranspose =
false;
3098 rap = hypre_ParCSRTMatMatKT(*P,Q,keepTranspose);
3099 hypre_ParCSRMatrixDestroy(Q);
3107#if MFEM_HYPRE_VERSION <= 22200
3108 HYPRE_Int P_owns_its_col_starts =
3109 hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*P));
3112 hypre_BoomerAMGBuildCoarseOperator(*P,*A,*P,&rap);
3114#if MFEM_HYPRE_VERSION <= 22200
3117 hypre_ParCSRMatrixSetRowStartsOwner(rap,0);
3118 hypre_ParCSRMatrixSetColStartsOwner(rap,0);
3119 if (P_owns_its_col_starts)
3121 hypre_ParCSRMatrixSetColStartsOwner(*P, 1);
3126 hypre_ParCSRMatrixSetNumNonzeros(rap);
3135 hypre_ParCSRMatrix * rap;
3137#ifdef HYPRE_USING_GPU
3140 hypre_ParCSRMatrix *Q = hypre_ParCSRMatMat(*A,*P);
3141 rap = hypre_ParCSRTMatMat(*Rt,Q);
3142 hypre_ParCSRMatrixDestroy(Q);
3147#if MFEM_HYPRE_VERSION <= 22200
3148 HYPRE_Int P_owns_its_col_starts =
3149 hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*P));
3150 HYPRE_Int Rt_owns_its_col_starts =
3151 hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*Rt));
3154 hypre_BoomerAMGBuildCoarseOperator(*Rt,*A,*P,&rap);
3156#if MFEM_HYPRE_VERSION <= 22200
3159 hypre_ParCSRMatrixSetRowStartsOwner(rap,0);
3160 hypre_ParCSRMatrixSetColStartsOwner(rap,0);
3161 if (P_owns_its_col_starts)
3163 hypre_ParCSRMatrixSetColStartsOwner(*P, 1);
3165 if (Rt_owns_its_col_starts)
3167 hypre_ParCSRMatrixSetColStartsOwner(*Rt, 1);
3172 hypre_ParCSRMatrixSetNumNonzeros(rap);
3181 const int num_loc,
const Array<int> &offsets,
3182 std::vector<int> &all_num_loc,
const int numBlocks,
3183 std::vector<std::vector<HYPRE_BigInt>> &blockProcOffsets,
3184 std::vector<HYPRE_BigInt> &procOffsets,
3185 std::vector<std::vector<int>> &procBlockOffsets,
3188 std::vector<std::vector<int>> all_block_num_loc(numBlocks);
3190 MPI_Allgather(
const_cast<int*
>(&num_loc), 1, MPI_INT, all_num_loc.data(), 1,
3193 for (
int j = 0; j < numBlocks; ++j)
3195 all_block_num_loc[j].resize(nprocs);
3196 blockProcOffsets[j].resize(nprocs);
3198 const int blockNumRows = offsets[j + 1] - offsets[j];
3199 MPI_Allgather(
const_cast<int*
>(&blockNumRows), 1, MPI_INT,
3200 all_block_num_loc[j].data(), 1,
3202 blockProcOffsets[j][0] = 0;
3203 for (
int i = 0; i < nprocs - 1; ++i)
3205 blockProcOffsets[j][i + 1] = blockProcOffsets[j][i]
3206 + all_block_num_loc[j][i];
3213 for (
int i = 0; i < nprocs; ++i)
3215 globalNum += all_num_loc[i];
3216 MFEM_VERIFY(globalNum >= 0,
"overflow in global size");
3219 firstLocal += all_num_loc[i];
3224 procOffsets[i + 1] = procOffsets[i] + all_num_loc[i];
3227 procBlockOffsets[i].resize(numBlocks);
3228 procBlockOffsets[i][0] = 0;
3229 for (
int j = 1; j < numBlocks; ++j)
3231 procBlockOffsets[i][j] = procBlockOffsets[i][j - 1]
3232 + all_block_num_loc[j - 1][i];
3240 const int numBlockRows = blocks.
NumRows();
3241 const int numBlockCols = blocks.
NumCols();
3243 MFEM_VERIFY(numBlockRows > 0 &&
3244 numBlockCols > 0,
"Invalid input to HypreParMatrixFromBlocks");
3246 if (blockCoeff != NULL)
3248 MFEM_VERIFY(numBlockRows == blockCoeff->
NumRows() &&
3249 numBlockCols == blockCoeff->
NumCols(),
3250 "Invalid input to HypreParMatrixFromBlocks");
3256 int nonNullBlockRow0 = -1;
3257 for (
int j=0; j<numBlockCols; ++j)
3259 if (blocks(0,j) != NULL)
3261 nonNullBlockRow0 = j;
3266 MFEM_VERIFY(nonNullBlockRow0 >= 0,
"Null row of blocks");
3267 MPI_Comm comm = blocks(0,nonNullBlockRow0)->GetComm();
3272 for (
int i=0; i<numBlockRows; ++i)
3274 for (
int j=0; j<numBlockCols; ++j)
3276 if (blocks(i,j) != NULL)
3278 const int nrows = blocks(i,j)->
NumRows();
3279 const int ncols = blocks(i,j)->
NumCols();
3281 if (rowOffsets[i+1] == 0)
3283 rowOffsets[i+1] = nrows;
3287 MFEM_VERIFY(rowOffsets[i+1] == nrows,
3288 "Inconsistent blocks in HypreParMatrixFromBlocks");
3291 if (colOffsets[j+1] == 0)
3293 colOffsets[j+1] = ncols;
3297 MFEM_VERIFY(colOffsets[j+1] == ncols,
3298 "Inconsistent blocks in HypreParMatrixFromBlocks");
3302 rowOffsets[i+1] += rowOffsets[i];
3305 for (
int j=0; j<numBlockCols; ++j)
3307 colOffsets[j+1] += colOffsets[j];
3310 const int num_loc_rows = rowOffsets[numBlockRows];
3311 const int num_loc_cols = colOffsets[numBlockCols];
3314 MPI_Comm_rank(comm, &rank);
3315 MPI_Comm_size(comm, &nprocs);
3317 std::vector<int> all_num_loc_rows(nprocs);
3318 std::vector<int> all_num_loc_cols(nprocs);
3319 std::vector<HYPRE_BigInt> procRowOffsets(nprocs);
3320 std::vector<HYPRE_BigInt> procColOffsets(nprocs);
3321 std::vector<std::vector<HYPRE_BigInt>> blockRowProcOffsets(numBlockRows);
3322 std::vector<std::vector<HYPRE_BigInt>> blockColProcOffsets(numBlockCols);
3323 std::vector<std::vector<int>> procBlockRowOffsets(nprocs);
3324 std::vector<std::vector<int>> procBlockColOffsets(nprocs);
3326 HYPRE_BigInt first_loc_row, glob_nrows, first_loc_col, glob_ncols;
3328 all_num_loc_rows, numBlockRows, blockRowProcOffsets,
3329 procRowOffsets, procBlockRowOffsets, first_loc_row,
3333 all_num_loc_cols, numBlockCols, blockColProcOffsets,
3334 procColOffsets, procBlockColOffsets, first_loc_col,
3337 std::vector<int> opI(num_loc_rows + 1);
3338 std::vector<int> cnt(num_loc_rows);
3340 for (
int i = 0; i < num_loc_rows; ++i)
3346 opI[num_loc_rows] = 0;
3351 for (
int i = 0; i < numBlockRows; ++i)
3353 for (
int j = 0; j < numBlockCols; ++j)
3355 if (blocks(i, j) == NULL)
3357 csr_blocks(i, j) = NULL;
3361 blocks(i, j)->HostRead();
3362 csr_blocks(i, j) = hypre_MergeDiagAndOffd(*blocks(i, j));
3363 blocks(i, j)->HypreRead();
3365 for (
int k = 0; k < csr_blocks(i, j)->num_rows; ++k)
3367 opI[rowOffsets[i] + k + 1] +=
3368 csr_blocks(i, j)->i[k + 1] - csr_blocks(i, j)->i[k];
3375 for (
int i = 0; i < num_loc_rows; ++i)
3377 opI[i + 1] += opI[i];
3380 const int nnz = opI[num_loc_rows];
3382 std::vector<HYPRE_BigInt> opJ(nnz);
3383 std::vector<real_t> data(nnz);
3386 for (
int i = 0; i < numBlockRows; ++i)
3388 for (
int j = 0; j < numBlockCols; ++j)
3390 if (csr_blocks(i, j) != NULL)
3392 const int nrows = csr_blocks(i, j)->num_rows;
3393 const real_t cij = blockCoeff ? (*blockCoeff)(i, j) : 1.0;
3394#if MFEM_HYPRE_VERSION >= 21600
3395 const bool usingBigJ = (csr_blocks(i, j)->big_j != NULL);
3398 for (
int k = 0; k < nrows; ++k)
3400 const int rowg = rowOffsets[i] + k;
3401 const int nnz_k = csr_blocks(i,j)->i[k+1]-csr_blocks(i,j)->i[k];
3402 const int osk = csr_blocks(i, j)->i[k];
3404 for (
int l = 0; l < nnz_k; ++l)
3407#if MFEM_HYPRE_VERSION >= 21600
3408 const HYPRE_Int bcol = usingBigJ ?
3409 csr_blocks(i, j)->big_j[osk + l] :
3410 csr_blocks(i, j)->j[osk + l];
3412 const HYPRE_Int bcol = csr_blocks(i, j)->j[osk + l];
3416 const auto &offs = blockColProcOffsets[j];
3417 const int bcolproc =
3418 std::upper_bound(offs.begin() + 1, offs.end(), bcol)
3421 opJ[opI[rowg] + cnt[rowg]] = procColOffsets[bcolproc] +
3422 procBlockColOffsets[bcolproc][j]
3424 - blockColProcOffsets[j][bcolproc];
3425 data[opI[rowg] + cnt[rowg]] = cij * csr_blocks(i, j)->data[osk + l];
3433 for (
int i = 0; i < numBlockRows; ++i)
3435 for (
int j = 0; j < numBlockCols; ++j)
3437 if (csr_blocks(i, j) != NULL)
3439 hypre_CSRMatrixDestroy(csr_blocks(i, j));
3444 MFEM_VERIFY(HYPRE_AssumedPartitionCheck(),
3445 "only 'assumed partition' mode is supported");
3447 std::vector<HYPRE_BigInt> rowStarts2(2);
3448 rowStarts2[0] = first_loc_row;
3449 rowStarts2[1] = first_loc_row + all_num_loc_rows[rank];
3451 int square = std::equal(all_num_loc_rows.begin(), all_num_loc_rows.end(),
3452 all_num_loc_cols.begin());
3455 return new HypreParMatrix(comm, num_loc_rows, glob_nrows, glob_ncols,
3456 opI.data(), opJ.data(),
3463 std::vector<HYPRE_BigInt> colStarts2(2);
3464 colStarts2[0] = first_loc_col;
3465 colStarts2[1] = first_loc_col + all_num_loc_cols[rank];
3467 return new HypreParMatrix(comm, num_loc_rows, glob_nrows, glob_ncols,
3468 opI.data(), opJ.data(),
3479 for (
int i = 0; i < blocks.
NumRows(); ++i)
3481 for (
int j = 0; j < blocks.
NumCols(); ++j)
3483 constBlocks(i, j) = blocks(i, j);
3509 hypre_CSRMatrix *A_diag = hypre_ParCSRMatrixDiag(A);
3510 HYPRE_Int num_rows = hypre_CSRMatrixNumRows(A_diag);
3512 real_t *u_data = hypre_VectorData(hypre_ParVectorLocalVector(
u));
3513 real_t *r_data = hypre_VectorData(hypre_ParVectorLocalVector(r));
3515 for (
int i = 0; i < N; i++)
3518 hypre_ParVectorCopy(
f, r);
3519 hypre_ParCSRMatrixMatvec(-1.0, A,
u, 1.0, r);
3522 (0 == (i % 2)) ? coef = lambda : coef =
mu;
3524 for (HYPRE_Int j = 0; j < num_rows; j++)
3526 u_data[j] += coef*r_data[j] / max_eig;
3542 hypre_ParVector *x0,
3543 hypre_ParVector *x1,
3544 hypre_ParVector *x2,
3545 hypre_ParVector *x3)
3548 hypre_CSRMatrix *A_diag = hypre_ParCSRMatrixDiag(A);
3549 HYPRE_Int num_rows = hypre_CSRMatrixNumRows(A_diag);
3551 real_t *u_data = hypre_VectorData(hypre_ParVectorLocalVector(
u));
3553 real_t *x0_data = hypre_VectorData(hypre_ParVectorLocalVector(x0));
3554 real_t *x1_data = hypre_VectorData(hypre_ParVectorLocalVector(x1));
3555 real_t *x2_data = hypre_VectorData(hypre_ParVectorLocalVector(x2));
3556 real_t *x3_data = hypre_VectorData(hypre_ParVectorLocalVector(x3));
3558 hypre_ParVectorCopy(
u, x0);
3561 hypre_ParVectorCopy(
f, x1);
3562 hypre_ParCSRMatrixMatvec(-1.0, A, x0, 1.0, x1);
3564 for (HYPRE_Int i = 0; i < num_rows; i++)
3566 x1_data[i] /= -max_eig;
3570 for (HYPRE_Int i = 0; i < num_rows; i++)
3572 x1_data[i] = x0_data[i] -x1_data[i];
3576 for (HYPRE_Int i = 0; i < num_rows; i++)
3578 x3_data[i] = fir_coeffs[0]*x0_data[i] +fir_coeffs[1]*x1_data[i];
3581 for (
int n = 2; n <= poly_order; n++)
3584 hypre_ParVectorCopy(
f, x2);
3585 hypre_ParCSRMatrixMatvec(-1.0, A, x1, 1.0, x2);
3587 for (HYPRE_Int i = 0; i < num_rows; i++)
3589 x2_data[i] /= -max_eig;
3597 for (HYPRE_Int i = 0; i < num_rows; i++)
3599 x2_data[i] = (x1_data[i]-x0_data[i]) +(x1_data[i]-2*x2_data[i]);
3600 x3_data[i] += fir_coeffs[n]*x2_data[i];
3601 x0_data[i] = x1_data[i];
3602 x1_data[i] = x2_data[i];
3606 for (HYPRE_Int i = 0; i < num_rows; i++)
3608 u_data[i] = x3_data[i];
3629 B =
X =
V =
Z = NULL;
3637 int relax_times_,
real_t relax_weight_,
3638 real_t omega_,
int poly_order_,
3639 real_t poly_fraction_,
int eig_est_cg_iter_)
3651 B =
X =
V =
Z = NULL;
3662 type =
static_cast<int>(type_);
3686 int eig_est_cg_iter_)
3694 int &eig_est_cg_iter_)
const
3711 int &taubin_iter_)
const
3721 if (!strcmp(name,
"Rectangular")) {
a = 1.0,
b = 0.0, c = 0.0; }
3722 if (!strcmp(name,
"Hanning")) {
a = 0.5,
b = 0.5, c = 0.0; }
3723 if (!strcmp(name,
"Hamming")) {
a = 0.54,
b = 0.46, c = 0.0; }
3724 if (!strcmp(name,
"Blackman")) {
a = 0.42,
b = 0.50, c = 0.08; }
3727 mfem_error(
"HypreSmoother::SetWindowByName : name not recognized!");
3752 mfem_error(
"HypreSmoother::SetOperator : not HypreParMatrix!");
3759 if (
B) {
delete B; }
3760 if (
X) {
delete X; }
3761 if (
V) {
delete V; }
3762 if (
Z) {
delete Z; }
3784 A->
Mult(ones, diag);
3795 d_l1_norms[i] = std::abs(d_l1_norms[i]);
3799#if MFEM_HYPRE_VERSION < 22100
3811#elif defined(HYPRE_USING_GPU)
3841#if MFEM_HYPRE_VERSION <= 22200
3850 else if (
type == 1001 ||
type == 1002)
3860#if MFEM_HYPRE_VERSION <= 22200
3902 window_coeffs[i] =
a +
b*cos(t) +c*cos(2*t);
3906 real_t theta_pb = acos(1.0 -0.5*k_pb);
3908 cheby_coeffs[0] = (theta_pb +
sigma)/M_PI;
3912 cheby_coeffs[i] = 2.0*sin(t)/(i*M_PI);
3917 fir_coeffs[i] = window_coeffs[i]*cheby_coeffs[i];
3920 delete[] window_coeffs;
3921 delete[] cheby_coeffs;
3928 mfem_error(
"HypreSmoother::Mult (...) : HypreParMatrix A is missing");
3941 HYPRE_ParCSRDiagScale(NULL, *
A,
b, x);
3948 hypre_ParVectorSetConstantValues(x, 0.0);
3969 else if (
type == 1002)
3983 int hypre_type =
type;
3985 if (
type == 5) { hypre_type = 1; }
3989 hypre_ParCSRRelax(*
A,
b, hypre_type,
3996 hypre_ParCSRRelax(*
A,
b, hypre_type,
4006 MFEM_ASSERT(
b.Size() ==
NumCols(),
"");
4011 mfem_error(
"HypreSmoother::Mult (...) : HypreParMatrix A is missing");
4018 A -> GetGlobalNumRows(),
4020 A -> GetRowStarts());
4022 A -> GetGlobalNumCols(),
4024 A -> GetColStarts());
4062 if (!xshallow) { x = *
X; }
4072 mfem_error(
"HypreSmoother::MultTranspose (...) : undefined!\n");
4078 if (
B) {
delete B; }
4079 if (
X) {
delete X; }
4080 if (
V) {
delete V; }
4081 if (
Z) {
delete Z; }
4090 if (
X0) {
delete X0; }
4091 if (
X1) {
delete X1; }
4106 :
Solver(A_->Height(), A_->Width())
4118 MFEM_ASSERT(
b.Size() ==
NumCols(),
"");
4121 MFEM_VERIFY(
A != NULL,
"HypreParMatrix A is missing");
4171 MFEM_VERIFY(
A != NULL,
"HypreParMatrix A is missing");
4173 HYPRE_Int err_flag =
SetupFcn()(*
this, *
A,
b, x);
4177 { MFEM_WARNING(
"Error during setup! Error code: " << err_flag); }
4181 MFEM_VERIFY(!err_flag,
"Error during setup! Error code: " << err_flag);
4183 hypre_error_flag = 0;
4191 if (!x_shallow) { x = *
X; }
4199 mfem_error(
"HypreSolver::Mult (...) : HypreParMatrix A is missing");
4206 hypre_ParVectorSetConstantValues(x, 0.0);
4218 { MFEM_WARNING(
"Error during solve! Error code: " << err_flag); }
4222 MFEM_VERIFY(!err_flag,
"Error during solve! Error code: " << err_flag);
4224 hypre_error_flag = 0;
4231 if (!x_shallow) { x = *
X; }
4236 if (
B) {
delete B; }
4237 if (
X) {
delete X; }
4242void HyprePCG::SetDefaultOptions()
4254 HYPRE_ParCSRPCGCreate(comm, &pcg_solver);
4255 SetDefaultOptions();
4264 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4266 HYPRE_ParCSRPCGCreate(comm, &pcg_solver);
4267 SetDefaultOptions();
4273 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
4294 HYPRE_PCGSetTwoNorm(pcg_solver, val);
4300 HYPRE_PCGGetTwoNorm(pcg_solver, &val);
4306 HYPRE_PCGSetTol(pcg_solver, tol);
4312 HYPRE_PCGGetTol(pcg_solver, &tol);
4318 HYPRE_PCGSetAbsoluteTol(pcg_solver, atol);
4324 hypre_PCGGetAbsoluteTol(pcg_solver, &atol);
4330 HYPRE_PCGSetMaxIter(pcg_solver, max_iter);
4336 HYPRE_PCGGetMaxIter(pcg_solver, &max_iter);
4342 HYPRE_PCGSetLogging(pcg_solver, logging);
4347 HYPRE_ParCSRPCGSetPrintLevel(pcg_solver, print_lvl);
4352 precond = &precond_;
4354 HYPRE_ParCSRPCGSetPrecond(pcg_solver,
4362 HYPRE_PCGSetTwoNorm(pcg_solver, 1);
4363 if (res_frequency > 0)
4365 HYPRE_PCGSetRecomputeResidualP(pcg_solver, res_frequency);
4369 HYPRE_PCGSetResidualTol(pcg_solver, rtol);
4376 HYPRE_Int time_index = 0;
4377 HYPRE_Int num_iterations;
4380 HYPRE_Int print_level;
4382 HYPRE_PCGGetPrintLevel(pcg_solver, &print_level);
4383 HYPRE_ParCSRPCGSetPrintLevel(pcg_solver, print_level%3);
4385 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4390 hypre_ParVectorSetConstantValues(x, 0.0);
4398 if (print_level > 0 && print_level < 3)
4400 time_index = hypre_InitializeTiming(
"PCG Setup");
4401 hypre_BeginTiming(time_index);
4404 HYPRE_ParCSRPCGSetup(pcg_solver, *
A,
b, x);
4407 if (print_level > 0 && print_level < 3)
4409 hypre_EndTiming(time_index);
4410 hypre_PrintTiming(
"Setup phase times", comm);
4411 hypre_FinalizeTiming(time_index);
4412 hypre_ClearTiming();
4416 if (print_level > 0 && print_level < 3)
4418 time_index = hypre_InitializeTiming(
"PCG Solve");
4419 hypre_BeginTiming(time_index);
4422 HYPRE_ParCSRPCGSolve(pcg_solver, *
A,
b, x);
4424 if (print_level > 0)
4426 if (print_level < 3)
4428 hypre_EndTiming(time_index);
4429 hypre_PrintTiming(
"Solve phase times", comm);
4430 hypre_FinalizeTiming(time_index);
4431 hypre_ClearTiming();
4434 HYPRE_ParCSRPCGGetNumIterations(pcg_solver, &num_iterations);
4435 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(pcg_solver,
4438 MPI_Comm_rank(comm, &myid);
4442 mfem::out <<
"PCG Iterations = " << num_iterations << endl
4443 <<
"Final PCG Relative Residual Norm = " << final_res_norm
4447 HYPRE_ParCSRPCGSetPrintLevel(pcg_solver, print_level);
4452 HYPRE_ParCSRPCGDestroy(pcg_solver);
4455#if MFEM_HYPRE_VERSION >= 21500
4459 HYPRE_ParCSRPCGGetResidual(pcg_solver, &r);
4466 final_res_norm =
ParNormlp(r,
p, r.GetComm());
4474 HYPRE_ParCSRGMRESCreate(comm, &gmres_solver);
4475 SetDefaultOptions();
4485 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4487 HYPRE_ParCSRGMRESCreate(comm, &gmres_solver);
4488 SetDefaultOptions();
4491void HypreGMRES::SetDefaultOptions()
4497 HYPRE_ParCSRGMRESSetKDim(gmres_solver, k_dim);
4498 HYPRE_ParCSRGMRESSetMaxIter(gmres_solver, max_iter);
4499 HYPRE_ParCSRGMRESSetTol(gmres_solver, tol);
4505 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
4524#if MFEM_HYPRE_VERSION >= 21500
4528 HYPRE_ParCSRGMRESGetResidual(gmres_solver, &r);
4535 final_res_norm =
ParNormlp(r,
p, r.GetComm());
4541 HYPRE_GMRESSetTol(gmres_solver, tol);
4547 HYPRE_GMRESGetTol(gmres_solver, &tol);
4553 HYPRE_GMRESSetAbsoluteTol(gmres_solver, tol);
4559 HYPRE_GMRESGetAbsoluteTol(gmres_solver, &atol);
4565 HYPRE_GMRESSetMaxIter(gmres_solver, max_iter);
4571 HYPRE_GMRESGetMaxIter(gmres_solver, &max_iter);
4577 HYPRE_GMRESSetKDim(gmres_solver, k_dim);
4583 HYPRE_GMRESGetKDim(gmres_solver, &k_dim);
4589 HYPRE_GMRESSetLogging(gmres_solver, logging);
4594 HYPRE_GMRESSetPrintLevel(gmres_solver, print_lvl);
4599 precond = &precond_;
4601 HYPRE_ParCSRGMRESSetPrecond(gmres_solver,
4610 HYPRE_Int time_index = 0;
4611 HYPRE_Int num_iterations;
4614 HYPRE_Int print_level;
4616 HYPRE_GMRESGetPrintLevel(gmres_solver, &print_level);
4618 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4623 hypre_ParVectorSetConstantValues(x, 0.0);
4631 if (print_level > 0)
4633 time_index = hypre_InitializeTiming(
"GMRES Setup");
4634 hypre_BeginTiming(time_index);
4637 HYPRE_ParCSRGMRESSetup(gmres_solver, *
A,
b, x);
4640 if (print_level > 0)
4642 hypre_EndTiming(time_index);
4643 hypre_PrintTiming(
"Setup phase times", comm);
4644 hypre_FinalizeTiming(time_index);
4645 hypre_ClearTiming();
4649 if (print_level > 0)
4651 time_index = hypre_InitializeTiming(
"GMRES Solve");
4652 hypre_BeginTiming(time_index);
4655 HYPRE_ParCSRGMRESSolve(gmres_solver, *
A,
b, x);
4657 if (print_level > 0)
4659 hypre_EndTiming(time_index);
4660 hypre_PrintTiming(
"Solve phase times", comm);
4661 hypre_FinalizeTiming(time_index);
4662 hypre_ClearTiming();
4664 HYPRE_ParCSRGMRESGetNumIterations(gmres_solver, &num_iterations);
4665 HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(gmres_solver,
4668 MPI_Comm_rank(comm, &myid);
4672 mfem::out <<
"GMRES Iterations = " << num_iterations << endl
4673 <<
"Final GMRES Relative Residual Norm = " << final_res_norm
4681 HYPRE_ParCSRGMRESDestroy(gmres_solver);
4689 HYPRE_ParCSRFlexGMRESCreate(comm, &fgmres_solver);
4690 SetDefaultOptions();
4700 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4702 HYPRE_ParCSRFlexGMRESCreate(comm, &fgmres_solver);
4703 SetDefaultOptions();
4706void HypreFGMRES::SetDefaultOptions()
4712 HYPRE_ParCSRFlexGMRESSetKDim(fgmres_solver, k_dim);
4713 HYPRE_ParCSRFlexGMRESSetMaxIter(fgmres_solver, max_iter);
4714 HYPRE_ParCSRFlexGMRESSetTol(fgmres_solver, tol);
4720 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
4741 HYPRE_ParCSRFlexGMRESSetTol(fgmres_solver, tol);
4747 HYPRE_FlexGMRESGetTol(fgmres_solver, &tol);
4753 HYPRE_ParCSRFlexGMRESSetMaxIter(fgmres_solver, max_iter);
4759 HYPRE_FlexGMRESGetMaxIter(fgmres_solver, &max_iter);
4765 HYPRE_ParCSRFlexGMRESSetKDim(fgmres_solver, k_dim);
4771 HYPRE_FlexGMRESGetKDim(fgmres_solver, &k_dim);
4777 HYPRE_ParCSRFlexGMRESSetLogging(fgmres_solver, logging);
4782 HYPRE_ParCSRFlexGMRESSetPrintLevel(fgmres_solver, print_lvl);
4787 precond = &precond_;
4788 HYPRE_ParCSRFlexGMRESSetPrecond(fgmres_solver,
4797 HYPRE_Int time_index = 0;
4798 HYPRE_Int num_iterations;
4801 HYPRE_Int print_level;
4803 HYPRE_FlexGMRESGetPrintLevel(fgmres_solver, &print_level);
4805 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4810 hypre_ParVectorSetConstantValues(x, 0.0);
4818 if (print_level > 0)
4820 time_index = hypre_InitializeTiming(
"FGMRES Setup");
4821 hypre_BeginTiming(time_index);
4824 HYPRE_ParCSRFlexGMRESSetup(fgmres_solver, *
A,
b, x);
4827 if (print_level > 0)
4829 hypre_EndTiming(time_index);
4830 hypre_PrintTiming(
"Setup phase times", comm);
4831 hypre_FinalizeTiming(time_index);
4832 hypre_ClearTiming();
4836 if (print_level > 0)
4838 time_index = hypre_InitializeTiming(
"FGMRES Solve");
4839 hypre_BeginTiming(time_index);
4842 HYPRE_ParCSRFlexGMRESSolve(fgmres_solver, *
A,
b, x);
4844 if (print_level > 0)
4846 hypre_EndTiming(time_index);
4847 hypre_PrintTiming(
"Solve phase times", comm);
4848 hypre_FinalizeTiming(time_index);
4849 hypre_ClearTiming();
4851 HYPRE_ParCSRFlexGMRESGetNumIterations(fgmres_solver, &num_iterations);
4852 HYPRE_ParCSRFlexGMRESGetFinalRelativeResidualNorm(fgmres_solver,
4855 MPI_Comm_rank(comm, &myid);
4859 mfem::out <<
"FGMRES Iterations = " << num_iterations << endl
4860 <<
"Final FGMRES Relative Residual Norm = " << final_res_norm
4868 HYPRE_ParCSRFlexGMRESDestroy(fgmres_solver);
4871#if MFEM_HYPRE_VERSION >= 21500
4875 HYPRE_ParCSRFlexGMRESGetResidual(fgmres_solver, &r);
4883 final_res_norm =
ParNormlp(r,
p, r.GetComm());
4890 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
4907 HYPRE_ParaSailsCreate(comm, &sai_precond);
4908 SetDefaultOptions();
4915 HYPRE_ParCSRMatrixGetComm(
A, &comm);
4917 HYPRE_ParaSailsCreate(comm, &sai_precond);
4918 SetDefaultOptions();
4921void HypreParaSails::SetDefaultOptions()
4923 int sai_max_levels = 1;
4924 real_t sai_threshold = 0.1;
4927 real_t sai_loadbal = 0.0;
4929 int sai_logging = 1;
4931 HYPRE_ParaSailsSetParams(sai_precond, sai_threshold, sai_max_levels);
4932 HYPRE_ParaSailsSetFilter(sai_precond, sai_filter);
4933 HYPRE_ParaSailsSetSym(sai_precond, sai_sym);
4934 HYPRE_ParaSailsSetLoadbal(sai_precond, sai_loadbal);
4935 HYPRE_ParaSailsSetReuse(sai_precond, sai_reuse);
4936 HYPRE_ParaSailsSetLogging(sai_precond, sai_logging);
4939void HypreParaSails::ResetSAIPrecond(MPI_Comm comm)
4941 HYPRE_Int sai_max_levels;
4942 HYPRE_Real sai_threshold;
4943 HYPRE_Real sai_filter;
4945 HYPRE_Real sai_loadbal;
4946 HYPRE_Int sai_reuse;
4947 HYPRE_Int sai_logging;
4950 HYPRE_ParaSailsGetNlevels(sai_precond, &sai_max_levels);
4951 HYPRE_ParaSailsGetThresh(sai_precond, &sai_threshold);
4952 HYPRE_ParaSailsGetFilter(sai_precond, &sai_filter);
4953 HYPRE_ParaSailsGetSym(sai_precond, &sai_sym);
4954 HYPRE_ParaSailsGetLoadbal(sai_precond, &sai_loadbal);
4955 HYPRE_ParaSailsGetReuse(sai_precond, &sai_reuse);
4956 HYPRE_ParaSailsGetLogging(sai_precond, &sai_logging);
4958 HYPRE_ParaSailsDestroy(sai_precond);
4959 HYPRE_ParaSailsCreate(comm, &sai_precond);
4961 HYPRE_ParaSailsSetParams(sai_precond, sai_threshold, sai_max_levels);
4962 HYPRE_ParaSailsSetFilter(sai_precond, sai_filter);
4963 HYPRE_ParaSailsSetSym(sai_precond, sai_sym);
4964 HYPRE_ParaSailsSetLoadbal(sai_precond, sai_loadbal);
4965 HYPRE_ParaSailsSetReuse(sai_precond, sai_reuse);
4966 HYPRE_ParaSailsSetLogging(sai_precond, sai_logging);
4972 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
4977 HYPRE_ParCSRMatrixGetComm(*
A, &comm);
4978 ResetSAIPrecond(comm);
4995 HYPRE_ParaSailsSetParams(sai_precond, threshold, max_levels);
5000 HYPRE_ParaSailsSetFilter(sai_precond, filter);
5005 HYPRE_ParaSailsSetSym(sai_precond, sym);
5010 HYPRE_ParaSailsSetLoadbal(sai_precond, loadbal);
5015 HYPRE_ParaSailsSetReuse(sai_precond, reuse);
5020 HYPRE_ParaSailsSetLogging(sai_precond, logging);
5025 HYPRE_ParaSailsDestroy(sai_precond);
5031 HYPRE_EuclidCreate(comm, &euc_precond);
5032 SetDefaultOptions();
5039 HYPRE_ParCSRMatrixGetComm(
A, &comm);
5041 HYPRE_EuclidCreate(comm, &euc_precond);
5042 SetDefaultOptions();
5045void HypreEuclid::SetDefaultOptions()
5053 HYPRE_EuclidSetLevel(euc_precond, euc_level);
5054 HYPRE_EuclidSetStats(euc_precond, euc_stats);
5055 HYPRE_EuclidSetMem(euc_precond, euc_mem);
5056 HYPRE_EuclidSetBJ(euc_precond, euc_bj);
5057 HYPRE_EuclidSetRowScale(euc_precond, euc_ro_sc);
5062 HYPRE_EuclidSetLevel(euc_precond, level);
5067 HYPRE_EuclidSetStats(euc_precond, stats);
5072 HYPRE_EuclidSetMem(euc_precond, mem);
5077 HYPRE_EuclidSetBJ(euc_precond, bj);
5082 HYPRE_EuclidSetRowScale(euc_precond, row_scale);
5085void HypreEuclid::ResetEuclidPrecond(MPI_Comm comm)
5089 HYPRE_EuclidDestroy(euc_precond);
5090 HYPRE_EuclidCreate(comm, &euc_precond);
5092 SetDefaultOptions();
5098 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
5103 HYPRE_ParCSRMatrixGetComm(*new_A, &comm);
5104 ResetEuclidPrecond(comm);
5121 HYPRE_EuclidDestroy(euc_precond);
5125#if MFEM_HYPRE_VERSION >= 21900
5128 HYPRE_ILUCreate(&ilu_precond);
5129 SetDefaultOptions();
5132void HypreILU::SetDefaultOptions()
5135 HYPRE_Int ilu_type = 0;
5136 HYPRE_ILUSetType(ilu_precond, ilu_type);
5139 HYPRE_Int max_iter = 1;
5140 HYPRE_ILUSetMaxIter(ilu_precond, max_iter);
5143 HYPRE_Real tol = 0.0;
5144 HYPRE_ILUSetTol(ilu_precond, tol);
5147 HYPRE_Int lev_fill = 1;
5148 HYPRE_ILUSetLevelOfFill(ilu_precond, lev_fill);
5151 HYPRE_Int reorder_type = 1;
5152 HYPRE_ILUSetLocalReordering(ilu_precond, reorder_type);
5155 HYPRE_Int print_level = 0;
5156 HYPRE_ILUSetPrintLevel(ilu_precond, print_level);
5159void HypreILU::ResetILUPrecond()
5163 HYPRE_ILUDestroy(ilu_precond);
5165 HYPRE_ILUCreate(&ilu_precond);
5166 SetDefaultOptions();
5171 HYPRE_ILUSetLevelOfFill(ilu_precond, lev_fill);
5176 HYPRE_ILUSetType(ilu_precond, ilu_type);
5181 HYPRE_ILUSetMaxIter(ilu_precond, max_iter);
5186 HYPRE_ILUSetTol(ilu_precond, tol);
5191 HYPRE_ILUSetLocalReordering(ilu_precond, reorder_type);
5196 HYPRE_ILUSetPrintLevel(ilu_precond, print_level);
5202 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
5204 if (
A) { ResetILUPrecond(); }
5220 HYPRE_ILUDestroy(ilu_precond);
5227 HYPRE_BoomerAMGCreate(&amg_precond);
5228 SetDefaultOptions();
5233 HYPRE_BoomerAMGCreate(&amg_precond);
5234 SetDefaultOptions();
5237void HypreBoomerAMG::SetDefaultOptions()
5240 int coarsen_type, agg_levels, interp_type, Pmax, relax_type, relax_sweeps,
5241 print_level, max_levels;
5283 HYPRE_BoomerAMGSetCoarsenType(amg_precond, coarsen_type);
5284 HYPRE_BoomerAMGSetAggNumLevels(amg_precond, agg_levels);
5285 HYPRE_BoomerAMGSetRelaxType(amg_precond, relax_type);
5288 HYPRE_BoomerAMGSetNumSweeps(amg_precond, relax_sweeps);
5289 HYPRE_BoomerAMGSetStrongThreshold(amg_precond, theta);
5290 HYPRE_BoomerAMGSetInterpType(amg_precond, interp_type);
5291 HYPRE_BoomerAMGSetPMaxElmts(amg_precond, Pmax);
5292 HYPRE_BoomerAMGSetPrintLevel(amg_precond, print_level);
5293 HYPRE_BoomerAMGSetMaxLevels(amg_precond, max_levels);
5296 HYPRE_BoomerAMGSetMaxIter(amg_precond, 1);
5297 HYPRE_BoomerAMGSetTol(amg_precond, 0.0);
5300void HypreBoomerAMG::ResetAMGPrecond()
5302 HYPRE_Int coarsen_type;
5303 HYPRE_Int agg_levels;
5304 HYPRE_Int relax_type;
5305 HYPRE_Int relax_sweeps;
5307 HYPRE_Int interp_type;
5309 HYPRE_Int print_level;
5310 HYPRE_Int max_levels;
5312 HYPRE_Int nrbms = rbms.
Size();
5314 HYPRE_Int nodal_diag;
5315 HYPRE_Int relax_coarse;
5316 HYPRE_Int interp_vec_variant;
5318 HYPRE_Int smooth_interp_vectors;
5319 HYPRE_Int interp_refine;
5321 hypre_ParAMGData *amg_data = (hypre_ParAMGData *)amg_precond;
5324 HYPRE_BoomerAMGGetCoarsenType(amg_precond, &coarsen_type);
5325 agg_levels = hypre_ParAMGDataAggNumLevels(amg_data);
5326 relax_type = hypre_ParAMGDataUserRelaxType(amg_data);
5327 relax_sweeps = hypre_ParAMGDataUserNumSweeps(amg_data);
5328 HYPRE_BoomerAMGGetStrongThreshold(amg_precond, &theta);
5329 hypre_BoomerAMGGetInterpType(amg_precond, &interp_type);
5330 HYPRE_BoomerAMGGetPMaxElmts(amg_precond, &Pmax);
5331 HYPRE_BoomerAMGGetPrintLevel(amg_precond, &print_level);
5332 HYPRE_BoomerAMGGetMaxLevels(amg_precond, &max_levels);
5333 HYPRE_BoomerAMGGetNumFunctions(amg_precond, &
dim);
5336 nodal = hypre_ParAMGDataNodal(amg_data);
5337 nodal_diag = hypre_ParAMGDataNodalDiag(amg_data);
5338 HYPRE_BoomerAMGGetCycleRelaxType(amg_precond, &relax_coarse, 3);
5339 interp_vec_variant = hypre_ParAMGInterpVecVariant(amg_data);
5340 q_max = hypre_ParAMGInterpVecQMax(amg_data);
5341 smooth_interp_vectors = hypre_ParAMGSmoothInterpVectors(amg_data);
5342 interp_refine = hypre_ParAMGInterpRefine(amg_data);
5345 HYPRE_BoomerAMGDestroy(amg_precond);
5346 HYPRE_BoomerAMGCreate(&amg_precond);
5348 HYPRE_BoomerAMGSetCoarsenType(amg_precond, coarsen_type);
5349 HYPRE_BoomerAMGSetAggNumLevels(amg_precond, agg_levels);
5350 HYPRE_BoomerAMGSetRelaxType(amg_precond, relax_type);
5351 HYPRE_BoomerAMGSetNumSweeps(amg_precond, relax_sweeps);
5352 HYPRE_BoomerAMGSetMaxLevels(amg_precond, max_levels);
5353 HYPRE_BoomerAMGSetTol(amg_precond, 0.0);
5354 HYPRE_BoomerAMGSetMaxIter(amg_precond, 1);
5355 HYPRE_BoomerAMGSetStrongThreshold(amg_precond, theta);
5356 HYPRE_BoomerAMGSetInterpType(amg_precond, interp_type);
5357 HYPRE_BoomerAMGSetPMaxElmts(amg_precond, Pmax);
5358 HYPRE_BoomerAMGSetPrintLevel(amg_precond, print_level);
5359 HYPRE_BoomerAMGSetNumFunctions(amg_precond,
dim);
5362 HYPRE_BoomerAMGSetNodal(amg_precond, nodal);
5363 HYPRE_BoomerAMGSetNodalDiag(amg_precond, nodal_diag);
5364 HYPRE_BoomerAMGSetCycleRelaxType(amg_precond, relax_coarse, 3);
5365 HYPRE_BoomerAMGSetInterpVecVariant(amg_precond, interp_vec_variant);
5366 HYPRE_BoomerAMGSetInterpVecQMax(amg_precond, q_max);
5367 HYPRE_BoomerAMGSetSmoothInterpVectors(amg_precond, smooth_interp_vectors);
5368 HYPRE_BoomerAMGSetInterpRefine(amg_precond, interp_refine);
5370 HYPRE_BoomerAMGSetInterpVectors(amg_precond, rbms.
Size(), rbms.
GetData());
5377 HYPRE_BoomerAMGGetMaxIter(amg_precond, &max_iter);
5384 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
5386 if (
A) { ResetAMGPrecond(); }
5402 HYPRE_BoomerAMGSetNumFunctions(amg_precond,
dim);
5410 HYPRE_Int *h_mapping = mfem_hypre_CTAlloc_host(HYPRE_Int,
height);
5412 MFEM_VERIFY(
height %
dim == 0,
"Ordering does not work as claimed!");
5414 for (
int i = 0; i <
dim; ++i)
5416 for (
int j = 0; j < h_nnodes; ++j)
5425 HYPRE_Int *mapping =
nullptr;
5426#if defined(hypre_IntArrayData) && defined(HYPRE_USING_GPU)
5429 mapping = mfem_hypre_CTAlloc(HYPRE_Int,
height);
5430 hypre_TMemcpy(mapping, h_mapping, HYPRE_Int,
height,
5431 HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
5432 mfem_hypre_TFree_host(h_mapping);
5437 mapping = h_mapping;
5442 HYPRE_BoomerAMGSetDofFunc(amg_precond, mapping);
5446 HYPRE_BoomerAMGSetAggNumLevels(amg_precond, 0);
5447 HYPRE_BoomerAMGSetStrongThreshold(amg_precond, 0.5);
5453 y = 0.0; y(0) = x(1); y(1) = -x(0);
5455static void func_ryz(
const Vector &x, Vector &y)
5457 y = 0.0; y(1) = x(2); y(2) = -x(1);
5459static void func_rzx(
const Vector &x, Vector &y)
5461 y = 0.0; y(2) = x(0); y(0) = -x(2);
5464void HypreBoomerAMG::RecomputeRBMs()
5467 Array<HypreParVector*> gf_rbms;
5470 for (
int i = 0; i < rbms.
Size(); i++)
5472 HYPRE_ParVectorDestroy(rbms[i]);
5479 VectorFunctionCoefficient coeff_rxy(2, func_rxy);
5481 ParGridFunction rbms_rxy(fespace);
5482 rbms_rxy.ProjectCoefficient(coeff_rxy);
5485 gf_rbms.SetSize(nrbms);
5487 rbms_rxy.GetTrueDofs(*gf_rbms[0]);
5493 VectorFunctionCoefficient coeff_rxy(3, func_rxy);
5494 VectorFunctionCoefficient coeff_ryz(3, func_ryz);
5495 VectorFunctionCoefficient coeff_rzx(3, func_rzx);
5497 ParGridFunction rbms_rxy(fespace);
5498 ParGridFunction rbms_ryz(fespace);
5499 ParGridFunction rbms_rzx(fespace);
5500 rbms_rxy.ProjectCoefficient(coeff_rxy);
5501 rbms_ryz.ProjectCoefficient(coeff_ryz);
5502 rbms_rzx.ProjectCoefficient(coeff_rzx);
5505 gf_rbms.SetSize(nrbms);
5509 rbms_rxy.GetTrueDofs(*gf_rbms[0]);
5510 rbms_ryz.GetTrueDofs(*gf_rbms[1]);
5511 rbms_rzx.GetTrueDofs(*gf_rbms[2]);
5520 for (
int i = 0; i < nrbms; i++)
5522 rbms[i] = gf_rbms[i]->StealParVector();
5528 bool interp_refine_)
5530#ifdef HYPRE_USING_GPU
5533 MFEM_ABORT(
"this method is not supported in hypre built with GPU support");
5538 this->fespace = fespace_;
5541 "The elasticity version of BoomerAMG requires Ordering::byVDIM");
5551 int relax_coarse = 8;
5554 int interp_vec_variant = 2;
5556 int smooth_interp_vectors = 1;
5560 int interp_refine = interp_refine_;
5562 HYPRE_BoomerAMGSetNodal(amg_precond, nodal);
5563 HYPRE_BoomerAMGSetNodalDiag(amg_precond, nodal_diag);
5564 HYPRE_BoomerAMGSetCycleRelaxType(amg_precond, relax_coarse, 3);
5565 HYPRE_BoomerAMGSetInterpVecVariant(amg_precond, interp_vec_variant);
5566 HYPRE_BoomerAMGSetInterpVecQMax(amg_precond, q_max);
5567 HYPRE_BoomerAMGSetSmoothInterpVectors(amg_precond, smooth_interp_vectors);
5568 HYPRE_BoomerAMGSetInterpRefine(amg_precond, interp_refine);
5571 HYPRE_BoomerAMGSetInterpVectors(amg_precond, rbms.
Size(), rbms.
GetData());
5580#if MFEM_HYPRE_VERSION >= 21800
5583 const std::string &prerelax,
5584 const std::string &postrelax)
5588 int interp_type = 100;
5589 int relax_type = 10;
5590 int coarsen_type = 6;
5591 real_t strength_tolC = 0.1;
5592 real_t strength_tolR = 0.01;
5593 real_t filter_tolR = 0.0;
5594 real_t filterA_tol = 0.0;
5597 int ns_down = 0, ns_up = 0, ns_coarse;
5600 ns_down =
static_cast<int>(prerelax.length());
5601 ns_up =
static_cast<int>(postrelax.length());
5605 HYPRE_Int **grid_relax_points = mfem_hypre_TAlloc(HYPRE_Int*, 4);
5606 grid_relax_points[0] = NULL;
5607 grid_relax_points[1] = mfem_hypre_TAlloc(HYPRE_Int, ns_down);
5608 grid_relax_points[2] = mfem_hypre_TAlloc(HYPRE_Int, ns_up);
5609 grid_relax_points[3] = mfem_hypre_TAlloc(HYPRE_Int, 1);
5610 grid_relax_points[3][0] = 0;
5613 for (
int i = 0; i<ns_down; i++)
5615 if (prerelax[i] ==
'F')
5617 grid_relax_points[1][i] = -1;
5619 else if (prerelax[i] ==
'C')
5621 grid_relax_points[1][i] = 1;
5623 else if (prerelax[i] ==
'A')
5625 grid_relax_points[1][i] = 0;
5630 for (
int i = 0; i<ns_up; i++)
5632 if (postrelax[i] ==
'F')
5634 grid_relax_points[2][i] = -1;
5636 else if (postrelax[i] ==
'C')
5638 grid_relax_points[2][i] = 1;
5640 else if (postrelax[i] ==
'A')
5642 grid_relax_points[2][i] = 0;
5646 HYPRE_BoomerAMGSetRestriction(amg_precond, distanceR);
5648 HYPRE_BoomerAMGSetGridRelaxPoints(amg_precond, grid_relax_points);
5650 HYPRE_BoomerAMGSetInterpType(amg_precond, interp_type);
5655 HYPRE_BoomerAMGSetSabs(amg_precond, Sabs);
5658 HYPRE_BoomerAMGSetCoarsenType(amg_precond, coarsen_type);
5661 HYPRE_BoomerAMGSetAggNumLevels(amg_precond, 0);
5663 HYPRE_BoomerAMGSetStrongThreshold(amg_precond, strength_tolC);
5667 HYPRE_BoomerAMGSetStrongThresholdR(amg_precond, strength_tolR);
5668 HYPRE_BoomerAMGSetFilterThresholdR(amg_precond, filter_tolR);
5671 if (relax_type > -1)
5673 HYPRE_BoomerAMGSetRelaxType(amg_precond, relax_type);
5678 HYPRE_BoomerAMGSetCycleNumSweeps(amg_precond, ns_coarse, 3);
5679 HYPRE_BoomerAMGSetCycleNumSweeps(amg_precond, ns_down, 1);
5680 HYPRE_BoomerAMGSetCycleNumSweeps(amg_precond, ns_up, 2);
5682 HYPRE_BoomerAMGSetADropTol(amg_precond, filterA_tol);
5684 HYPRE_BoomerAMGSetADropType(amg_precond, -1);
5692 for (
int i = 0; i < rbms.
Size(); i++)
5694 HYPRE_ParVectorDestroy(rbms[i]);
5697 HYPRE_BoomerAMGDestroy(amg_precond);
5723 MFEM_ASSERT(G != NULL,
"");
5724 MFEM_ASSERT(x != NULL,
"");
5725 MFEM_ASSERT(y != NULL,
"");
5726 int sdim = (z == NULL) ? 2 : 3;
5727 int cycle_type = 13;
5728 MakeSolver(sdim, cycle_type);
5730 HYPRE_ParVector pz = z ?
static_cast<HYPRE_ParVector
>(*z) : NULL;
5731 HYPRE_AMSSetCoordinateVectors(ams, *x, *y, pz);
5732 HYPRE_AMSSetDiscreteGradient(ams, *G);
5740 int cycle_type = 13;
5745 trace_space = trace_space || rt_trace_space;
5751 "HypreAMS does not support variable order spaces");
5758 MakeSolver(std::max(sdim, vdim), cycle_type);
5759 MakeGradientAndInterpolation(edge_fespace, cycle_type);
5763 delete edge_fespace;
5768void HypreAMS::MakeSolver(
int sdim,
int cycle_type)
5774 int amg_coarsen_type = hypre_gpu ? 8 : 10;
5775 int amg_agg_levels = hypre_gpu ? 0 : 1;
5776 int amg_rlx_type = hypre_gpu ? 18 : 8;
5777 int rlx_type = hypre_gpu ? 1: 2;
5779 int amg_interp_type = 6;
5783 ams_cycle_type = cycle_type;
5784 HYPRE_AMSCreate(&ams);
5786 HYPRE_AMSSetDimension(ams, sdim);
5787 HYPRE_AMSSetTol(ams, 0.0);
5788 HYPRE_AMSSetMaxIter(ams, 1);
5789 HYPRE_AMSSetCycleType(ams, cycle_type);
5790 HYPRE_AMSSetPrintLevel(ams, 1);
5793 HYPRE_AMSSetSmoothingOptions(ams, rlx_type, rlx_sweeps, rlx_weight, rlx_omega);
5794 HYPRE_AMSSetAlphaAMGOptions(ams, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
5795 theta, amg_interp_type, amg_Pmax);
5796 HYPRE_AMSSetBetaAMGOptions(ams, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
5797 theta, amg_interp_type, amg_Pmax);
5799 HYPRE_AMSSetAlphaAMGCoarseRelaxType(ams, amg_rlx_type);
5800 HYPRE_AMSSetBetaAMGCoarseRelaxType(ams, amg_rlx_type);
5809void HypreAMS::MakeGradientAndInterpolation(
5810 ParFiniteElementSpace *edge_fespace,
int cycle_type)
5812 const FiniteElementCollection *edge_fec = edge_fespace->FEColl();
5813 bool trace_space =
dynamic_cast<const ND_Trace_FECollection *
>(edge_fec);
5815 ParMesh *pmesh = edge_fespace->GetParMesh();
5817 int sdim = pmesh->SpaceDimension();
5818 int vdim = edge_fespace->FEColl()->GetRangeDim(
dim - trace_space);
5821 MFEM_VERIFY(!edge_fespace->IsVariableOrder(),
5822 "HypreAMS does not support variable order spaces");
5823 int p = edge_fec->GetOrder() + (
dim - trace_space == 1 ? 1 : 0);
5826 FiniteElementCollection *vert_fec;
5829 vert_fec =
new H1_Trace_FECollection(
p,
dim);
5833 vert_fec =
new H1_FECollection(
p,
dim);
5835 ParFiniteElementSpace *vert_fespace =
new ParFiniteElementSpace(pmesh,
5839 ParDiscreteLinearOperator *grad;
5840 grad =
new ParDiscreteLinearOperator(vert_fespace, edge_fespace);
5843 grad->AddTraceFaceInterpolator(
new GradientInterpolator);
5845 else if (
dynamic_cast<const RT_FECollection *
>(edge_fec))
5847 grad->AddDomainInterpolator(
new CurlInterpolator);
5851 grad->AddDomainInterpolator(
new GradientInterpolator);
5855 G = grad->ParallelAssemble();
5856 HYPRE_AMSSetDiscreteGradient(ams, *G);
5861 Pi = Pix = Piy = Piz = NULL;
5862 if (
p == 1 && pmesh->GetNodes() == NULL && vdim <= sdim)
5864 ParGridFunction x_coord(vert_fespace);
5865 ParGridFunction y_coord(vert_fespace);
5866 ParGridFunction z_coord(vert_fespace);
5868 for (
int i = 0; i < pmesh->GetNV(); i++)
5870 coord = pmesh -> GetVertex(i);
5871 x_coord(i) = coord[0];
5872 if (sdim >= 2) { y_coord(i) = coord[1]; }
5873 if (sdim == 3) { z_coord(i) = coord[2]; }
5875 x = x_coord.ParallelProject();
5882 y = y_coord.ParallelProject();
5887 z = z_coord.ParallelProject();
5891 HYPRE_AMSSetCoordinateVectors(ams,
5892 x ? (HYPRE_ParVector)(*x) : NULL,
5893 y ? (HYPRE_ParVector)(*y) : NULL,
5894 z ? (HYPRE_ParVector)(*z) : NULL);
5898 ParFiniteElementSpace *vert_fespace_d =
5899 new ParFiniteElementSpace(pmesh, vert_fec, std::max(sdim, vdim),
5902 ParDiscreteLinearOperator *id_ND;
5903 id_ND =
new ParDiscreteLinearOperator(vert_fespace_d, edge_fespace);
5906 id_ND->AddTraceFaceInterpolator(
new IdentityInterpolator);
5910 id_ND->AddDomainInterpolator(
new IdentityInterpolator);
5915 if (cycle_type < 10)
5917 Pi = id_ND->ParallelAssemble();
5921 Array2D<HypreParMatrix *> Pi_blocks;
5922 id_ND->GetParBlocks(Pi_blocks);
5923 Pix = Pi_blocks(0,0);
5924 if (std::max(sdim, vdim) >= 2) { Piy = Pi_blocks(0,1); }
5925 if (std::max(sdim, vdim) == 3) { Piz = Pi_blocks(0,2); }
5930 HYPRE_ParCSRMatrix HY_Pi = (Pi) ? (HYPRE_ParCSRMatrix) *Pi : NULL;
5931 HYPRE_ParCSRMatrix HY_Pix = (Pix) ? (HYPRE_ParCSRMatrix) *Pix : NULL;
5932 HYPRE_ParCSRMatrix HY_Piy = (Piy) ? (HYPRE_ParCSRMatrix) *Piy : NULL;
5933 HYPRE_ParCSRMatrix HY_Piz = (Piz) ? (HYPRE_ParCSRMatrix) *Piz : NULL;
5934 HYPRE_AMSSetInterpolations(ams, HY_Pi, HY_Pix, HY_Piy, HY_Piz);
5936 delete vert_fespace_d;
5939 delete vert_fespace;
5943void HypreAMS::ResetAMSPrecond()
5945#if MFEM_HYPRE_VERSION >= 22600
5947 auto *ams_data = (hypre_AMSData *)ams;
5950 HYPRE_Int
dim = hypre_AMSDataDimension(ams_data);
5953 hypre_ParCSRMatrix *hy_G = hypre_AMSDataDiscreteGradient(ams_data);
5955 HYPRE_Int beta_is_zero = hypre_AMSDataBetaIsZero(ams_data);
5958 hypre_ParCSRMatrix *hy_Pi hypre_AMSDataPiInterpolation(ams_data);
5959 hypre_ParCSRMatrix *hy_Pix = ams_data->Pix;
5960 hypre_ParCSRMatrix *hy_Piy = ams_data->Piy;
5961 hypre_ParCSRMatrix *hy_Piz = ams_data->Piz;
5962 HYPRE_Int owns_Pi = hypre_AMSDataOwnsPiInterpolation(ams_data);
5965 ams_data->owns_Pi = 0;
5969 hypre_ParVector *hy_x = hypre_AMSDataVertexCoordinateX(ams_data);
5970 hypre_ParVector *hy_y = hypre_AMSDataVertexCoordinateY(ams_data);
5971 hypre_ParVector *hy_z = hypre_AMSDataVertexCoordinateZ(ams_data);
5974 HYPRE_Int maxit = hypre_AMSDataMaxIter(ams_data);
5975 HYPRE_Real tol = hypre_AMSDataTol(ams_data);
5976 HYPRE_Int cycle_type = hypre_AMSDataCycleType(ams_data);
5977 HYPRE_Int ams_print_level = hypre_AMSDataPrintLevel(ams_data);
5980 HYPRE_Int A_relax_type = hypre_AMSDataARelaxType(ams_data);
5981 HYPRE_Int A_relax_times = hypre_AMSDataARelaxTimes(ams_data);
5982 HYPRE_Real A_relax_weight = hypre_AMSDataARelaxWeight(ams_data);
5983 HYPRE_Real A_omega = hypre_AMSDataAOmega(ams_data);
5984 HYPRE_Int A_cheby_order = hypre_AMSDataAChebyOrder(ams_data);
5985 HYPRE_Real A_cheby_fraction = hypre_AMSDataAChebyFraction(ams_data);
5987 HYPRE_Int B_Pi_coarsen_type = hypre_AMSDataPoissonAlphaAMGCoarsenType(ams_data);
5988 HYPRE_Int B_Pi_agg_levels = hypre_AMSDataPoissonAlphaAMGAggLevels(ams_data);
5989 HYPRE_Int B_Pi_relax_type = hypre_AMSDataPoissonAlphaAMGRelaxType(ams_data);
5990 HYPRE_Int B_Pi_coarse_relax_type = ams_data->B_Pi_coarse_relax_type;
5991 HYPRE_Real B_Pi_theta = hypre_AMSDataPoissonAlphaAMGStrengthThreshold(ams_data);
5992 HYPRE_Int B_Pi_interp_type = ams_data->B_Pi_interp_type;
5993 HYPRE_Int B_Pi_Pmax = ams_data->B_Pi_Pmax;
5995 HYPRE_Int B_G_coarsen_type = hypre_AMSDataPoissonBetaAMGCoarsenType(ams_data);
5996 HYPRE_Int B_G_agg_levels = hypre_AMSDataPoissonBetaAMGAggLevels(ams_data);
5997 HYPRE_Int B_G_relax_type = hypre_AMSDataPoissonBetaAMGRelaxType(ams_data);
5998 HYPRE_Int B_G_coarse_relax_type = ams_data->B_G_coarse_relax_type;
5999 HYPRE_Real B_G_theta = hypre_AMSDataPoissonBetaAMGStrengthThreshold(ams_data);
6000 HYPRE_Int B_G_interp_type = ams_data->B_G_interp_type;
6001 HYPRE_Int B_G_Pmax = ams_data->B_G_Pmax;
6003 HYPRE_AMSDestroy(ams);
6004 HYPRE_AMSCreate(&ams);
6005 ams_data = (hypre_AMSData *)ams;
6007 HYPRE_AMSSetDimension(ams,
dim);
6008 HYPRE_AMSSetTol(ams, tol);
6009 HYPRE_AMSSetMaxIter(ams, maxit);
6010 HYPRE_AMSSetCycleType(ams, cycle_type);
6011 HYPRE_AMSSetPrintLevel(ams, ams_print_level);
6013 HYPRE_AMSSetCoordinateVectors(ams, hy_x, hy_y, hy_z);
6015 HYPRE_AMSSetDiscreteGradient(ams, hy_G);
6016 HYPRE_AMSSetCoordinateVectors(ams, hy_x, hy_y, hy_z);
6017 HYPRE_AMSSetInterpolations(ams, hy_Pi, hy_Pix, hy_Piy, hy_Piz);
6018 ams_data->owns_Pi = owns_Pi;
6021 HYPRE_AMSSetSmoothingOptions(ams, A_relax_type, A_relax_times, A_relax_weight,
6024 hypre_AMSDataAChebyOrder(ams_data) = A_cheby_order;
6025 hypre_AMSDataAChebyFraction(ams_data) = A_cheby_fraction;
6027 HYPRE_AMSSetAlphaAMGOptions(ams, B_Pi_coarsen_type, B_Pi_agg_levels,
6029 B_Pi_theta, B_Pi_interp_type, B_Pi_Pmax);
6030 HYPRE_AMSSetBetaAMGOptions(ams, B_G_coarsen_type, B_G_agg_levels,
6032 B_G_theta, B_G_interp_type, B_G_Pmax);
6034 HYPRE_AMSSetAlphaAMGCoarseRelaxType(ams, B_Pi_coarse_relax_type);
6035 HYPRE_AMSSetBetaAMGCoarseRelaxType(ams, B_G_coarse_relax_type);
6037 ams_data->beta_is_zero = beta_is_zero;
6040 HYPRE_AMSDestroy(ams);
6042 MakeSolver(space_dim, ams_cycle_type);
6044 HYPRE_AMSSetPrintLevel(ams, print_level);
6045 if (singular) { HYPRE_AMSSetBetaPoissonMatrix(ams, NULL); }
6047 HYPRE_AMSSetDiscreteGradient(ams, *G);
6050 HYPRE_AMSSetCoordinateVectors(ams,
6051 x ? (HYPRE_ParVector)(*x) : nullptr,
6052 y ? (HYPRE_ParVector)(*y) : nullptr,
6053 z ? (HYPRE_ParVector)(*z) : nullptr);
6057 HYPRE_AMSSetInterpolations(ams,
6058 Pi ? (HYPRE_ParCSRMatrix) *Pi : nullptr,
6059 Pix ? (HYPRE_ParCSRMatrix) *Pix : nullptr,
6060 Piy ? (HYPRE_ParCSRMatrix) *Piy : nullptr,
6061 Piz ? (HYPRE_ParCSRMatrix) *Piz : nullptr);
6069 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
6071 if (
A) { ResetAMSPrecond(); }
6088 HYPRE_AMSDestroy(ams);
6103 HYPRE_AMSSetPrintLevel(ams, print_lvl);
6104 print_level = print_lvl;
6122 x(x_), y(y_), z(z_),
6124 ND_Pi(NULL), ND_Pix(NULL), ND_Piy(NULL), ND_Piz(NULL),
6125 RT_Pi(NULL), RT_Pix(NULL), RT_Piy(NULL), RT_Piz(NULL)
6127 MFEM_ASSERT(C != NULL,
"");
6128 MFEM_ASSERT(G != NULL,
"");
6129 MFEM_ASSERT(x != NULL,
"");
6130 MFEM_ASSERT(y != NULL,
"");
6131 MFEM_ASSERT(z != NULL,
"");
6135 HYPRE_ADSSetCoordinateVectors(ads, *x, *y, *z);
6136 HYPRE_ADSSetDiscreteCurl(ads, *C);
6137 HYPRE_ADSSetDiscreteGradient(ads, *G);
6140void HypreADS::MakeSolver()
6146 int rlx_type = hypre_gpu ? 1 : 2;
6147 int amg_coarsen_type = hypre_gpu ? 8 : 10;
6148 int amg_agg_levels = hypre_gpu ? 0 : 1;
6149 int amg_rlx_type = hypre_gpu ? 18 : 8;
6151 int amg_interp_type = 6;
6154 HYPRE_ADSCreate(&ads);
6156 HYPRE_ADSSetTol(ads, 0.0);
6157 HYPRE_ADSSetMaxIter(ads, 1);
6158 HYPRE_ADSSetCycleType(ads, cycle_type);
6159 HYPRE_ADSSetPrintLevel(ads, 1);
6162 HYPRE_ADSSetSmoothingOptions(ads, rlx_type, rlx_sweeps, rlx_weight, rlx_omega);
6163 HYPRE_ADSSetAMGOptions(ads, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
6164 theta, amg_interp_type, amg_Pmax);
6165 HYPRE_ADSSetAMSOptions(ads, ams_cycle_type, amg_coarsen_type, amg_agg_levels,
6166 amg_rlx_type, theta, amg_interp_type, amg_Pmax);
6175void HypreADS::MakeDiscreteMatrices(ParFiniteElementSpace *face_fespace)
6177 const FiniteElementCollection *face_fec = face_fespace->FEColl();
6179 (
dynamic_cast<const RT_Trace_FECollection*
>(face_fec) != NULL);
6181 MFEM_VERIFY(!face_fespace->IsVariableOrder(),
"");
6182 int p = face_fec->GetOrder();
6185 ParMesh *pmesh = (ParMesh *) face_fespace->GetMesh();
6186 FiniteElementCollection *vert_fec, *edge_fec;
6189 vert_fec =
new H1_Trace_FECollection(
p, 3);
6190 edge_fec =
new ND_Trace_FECollection(
p, 3);
6194 vert_fec =
new H1_FECollection(
p, 3);
6195 edge_fec =
new ND_FECollection(
p, 3);
6198 ParFiniteElementSpace *vert_fespace =
new ParFiniteElementSpace(pmesh,
6200 ParFiniteElementSpace *edge_fespace =
new ParFiniteElementSpace(pmesh,
6204 if (
p == 1 && pmesh->GetNodes() == NULL)
6206 ParGridFunction x_coord(vert_fespace);
6207 ParGridFunction y_coord(vert_fespace);
6208 ParGridFunction z_coord(vert_fespace);
6210 for (
int i = 0; i < pmesh->GetNV(); i++)
6212 coord = pmesh -> GetVertex(i);
6213 x_coord(i) = coord[0];
6214 y_coord(i) = coord[1];
6215 z_coord(i) = coord[2];
6217 x = x_coord.ParallelProject();
6218 y = y_coord.ParallelProject();
6219 z = z_coord.ParallelProject();
6223 HYPRE_ADSSetCoordinateVectors(ads, *x, *y, *z);
6233 ParDiscreteLinearOperator *curl;
6234 curl =
new ParDiscreteLinearOperator(edge_fespace, face_fespace);
6237 curl->AddTraceFaceInterpolator(
new CurlInterpolator);
6241 curl->AddDomainInterpolator(
new CurlInterpolator);
6245 C = curl->ParallelAssemble();
6247 HYPRE_ADSSetDiscreteCurl(ads, *C);
6251 ParDiscreteLinearOperator *grad;
6252 grad =
new ParDiscreteLinearOperator(vert_fespace, edge_fespace);
6255 grad->AddTraceFaceInterpolator(
new GradientInterpolator);
6259 grad->AddDomainInterpolator(
new GradientInterpolator);
6263 G = grad->ParallelAssemble();
6266 HYPRE_ADSSetDiscreteGradient(ads, *G);
6270 RT_Pi = RT_Pix = RT_Piy = RT_Piz = NULL;
6271 ND_Pi = ND_Pix = ND_Piy = ND_Piz = NULL;
6272 if (
p > 1 || pmesh->GetNodes() != NULL)
6274 ParFiniteElementSpace *vert_fespace_d
6277 ParDiscreteLinearOperator *id_ND;
6278 id_ND =
new ParDiscreteLinearOperator(vert_fespace_d, edge_fespace);
6281 id_ND->AddTraceFaceInterpolator(
new IdentityInterpolator);
6285 id_ND->AddDomainInterpolator(
new IdentityInterpolator);
6290 if (ams_cycle_type < 10)
6292 ND_Pi = id_ND->ParallelAssemble();
6298 Array2D<HypreParMatrix *> ND_Pi_blocks;
6299 id_ND->GetParBlocks(ND_Pi_blocks);
6300 ND_Pix = ND_Pi_blocks(0,0);
6301 ND_Piy = ND_Pi_blocks(0,1);
6302 ND_Piz = ND_Pi_blocks(0,2);
6307 ParDiscreteLinearOperator *id_RT;
6308 id_RT =
new ParDiscreteLinearOperator(vert_fespace_d, face_fespace);
6311 id_RT->AddTraceFaceInterpolator(
new NormalInterpolator);
6315 id_RT->AddDomainInterpolator(
new IdentityInterpolator);
6320 if (cycle_type < 10)
6322 RT_Pi = id_RT->ParallelAssemble();
6327 Array2D<HypreParMatrix *> RT_Pi_blocks;
6328 id_RT->GetParBlocks(RT_Pi_blocks);
6329 RT_Pix = RT_Pi_blocks(0,0);
6330 RT_Piy = RT_Pi_blocks(0,1);
6331 RT_Piz = RT_Pi_blocks(0,2);
6336 HYPRE_ParCSRMatrix HY_RT_Pi, HY_RT_Pix, HY_RT_Piy, HY_RT_Piz;
6337 HY_RT_Pi = (RT_Pi) ? (HYPRE_ParCSRMatrix) *RT_Pi : NULL;
6338 HY_RT_Pix = (RT_Pix) ? (HYPRE_ParCSRMatrix) *RT_Pix : NULL;
6339 HY_RT_Piy = (RT_Piy) ? (HYPRE_ParCSRMatrix) *RT_Piy : NULL;
6340 HY_RT_Piz = (RT_Piz) ? (HYPRE_ParCSRMatrix) *RT_Piz : NULL;
6341 HYPRE_ParCSRMatrix HY_ND_Pi, HY_ND_Pix, HY_ND_Piy, HY_ND_Piz;
6342 HY_ND_Pi = (ND_Pi) ? (HYPRE_ParCSRMatrix) *ND_Pi : NULL;
6343 HY_ND_Pix = (ND_Pix) ? (HYPRE_ParCSRMatrix) *ND_Pix : NULL;
6344 HY_ND_Piy = (ND_Piy) ? (HYPRE_ParCSRMatrix) *ND_Piy : NULL;
6345 HY_ND_Piz = (ND_Piz) ? (HYPRE_ParCSRMatrix) *ND_Piz : NULL;
6346 HYPRE_ADSSetInterpolations(ads,
6347 HY_RT_Pi, HY_RT_Pix, HY_RT_Piy, HY_RT_Piz,
6348 HY_ND_Pi, HY_ND_Pix, HY_ND_Piy, HY_ND_Piz);
6350 delete vert_fespace_d;
6354 delete vert_fespace;
6356 delete edge_fespace;
6359void HypreADS::Init(ParFiniteElementSpace *face_fespace)
6362 MakeDiscreteMatrices(face_fespace);
6365void HypreADS::ResetADSPrecond()
6367 HYPRE_ADSDestroy(ads);
6371 HYPRE_ADSSetPrintLevel(ads, print_level);
6373 HYPRE_ADSSetDiscreteCurl(ads, *C);
6374 HYPRE_ADSSetDiscreteGradient(ads, *G);
6377 MFEM_VERIFY(x && y && z,
"");
6378 HYPRE_ADSSetCoordinateVectors(ads, *x, *y, *z);
6382 HYPRE_ParCSRMatrix HY_RT_Pi, HY_RT_Pix, HY_RT_Piy, HY_RT_Piz;
6383 HY_RT_Pi = (RT_Pi) ? (HYPRE_ParCSRMatrix) *RT_Pi : NULL;
6384 HY_RT_Pix = (RT_Pix) ? (HYPRE_ParCSRMatrix) *RT_Pix : NULL;
6385 HY_RT_Piy = (RT_Piy) ? (HYPRE_ParCSRMatrix) *RT_Piy : NULL;
6386 HY_RT_Piz = (RT_Piz) ? (HYPRE_ParCSRMatrix) *RT_Piz : NULL;
6387 HYPRE_ParCSRMatrix HY_ND_Pi, HY_ND_Pix, HY_ND_Piy, HY_ND_Piz;
6388 HY_ND_Pi = (ND_Pi) ? (HYPRE_ParCSRMatrix) *ND_Pi : NULL;
6389 HY_ND_Pix = (ND_Pix) ? (HYPRE_ParCSRMatrix) *ND_Pix : NULL;
6390 HY_ND_Piy = (ND_Piy) ? (HYPRE_ParCSRMatrix) *ND_Piy : NULL;
6391 HY_ND_Piz = (ND_Piz) ? (HYPRE_ParCSRMatrix) *ND_Piz : NULL;
6392 HYPRE_ADSSetInterpolations(ads,
6393 HY_RT_Pi, HY_RT_Pix, HY_RT_Piy, HY_RT_Piz,
6394 HY_ND_Pi, HY_ND_Pix, HY_ND_Piy, HY_ND_Piz);
6401 MFEM_VERIFY(new_A,
"new Operator must be a HypreParMatrix!");
6403 if (
A) { ResetADSPrecond(); }
6420 HYPRE_ADSDestroy(ads);
6442 HYPRE_ADSSetPrintLevel(ads, print_lvl);
6443 print_level = print_lvl;
6446HypreLOBPCG::HypreMultiVector::HypreMultiVector(
int n,
HypreParVector & v,
6447 mv_InterfaceInterpreter & interpreter)
6451 mv_ptr = mv_MultiVectorCreateFromSampleVector(&interpreter, nv,
6452 (HYPRE_ParVector)v);
6454 HYPRE_ParVector* vecs = NULL;
6456 mv_TempMultiVector* tmp =
6457 (mv_TempMultiVector*)mv_MultiVectorGetData(mv_ptr);
6458 vecs = (HYPRE_ParVector*)(tmp -> vector);
6461 hpv =
new HypreParVector*[nv];
6462 for (
int i=0; i<nv; i++)
6464 hpv[i] =
new HypreParVector(vecs[i]);
6468HypreLOBPCG::HypreMultiVector::~HypreMultiVector()
6472 for (
int i=0; i<nv; i++)
6479 mv_MultiVectorDestroy(mv_ptr);
6483HypreLOBPCG::HypreMultiVector::Randomize(HYPRE_Int seed_)
6485 mv_MultiVectorSetRandom(mv_ptr, seed_);
6489HypreLOBPCG::HypreMultiVector::GetVector(
unsigned int i)
6491 MFEM_ASSERT((
int)i < nv,
"index out of range");
6497HypreLOBPCG::HypreMultiVector::StealVectors()
6499 HypreParVector ** hpv_ret = hpv;
6503 mv_TempMultiVector * mv_tmp =
6504 (mv_TempMultiVector*)mv_MultiVectorGetData(mv_ptr);
6506 mv_tmp->ownsVectors = 0;
6508 for (
int i=0; i<nv; i++)
6510 hpv_ret[i]->SetOwnership(1);
6528 MPI_Comm_size(comm,&numProcs);
6529 MPI_Comm_rank(comm,&myid);
6531 HYPRE_ParCSRSetupInterpreter(&interpreter);
6532 HYPRE_ParCSRSetupMatvec(&matvec_fn);
6533 HYPRE_LOBPCGCreate(&interpreter, &matvec_fn, &lobpcg_solver);
6542 HYPRE_LOBPCGDestroy(lobpcg_solver);
6548 HYPRE_LOBPCGSetTol(lobpcg_solver, tol);
6554#if MFEM_HYPRE_VERSION >= 21101
6555 HYPRE_LOBPCGSetRTol(lobpcg_solver, rel_tol);
6557 MFEM_ABORT(
"This method requires HYPRE version >= 2.11.1");
6564 HYPRE_LOBPCGSetMaxIter(lobpcg_solver, max_iter);
6572 HYPRE_LOBPCGSetPrintLevel(lobpcg_solver, logging);
6579 HYPRE_LOBPCGSetPrecondUsageMode(lobpcg_solver, pcg_mode);
6585 HYPRE_LOBPCGSetPrecond(lobpcg_solver,
6586 (HYPRE_PtrToSolverFcn)this->PrecondSolve,
6587 (HYPRE_PtrToSolverFcn)this->PrecondSetup,
6588 (HYPRE_Solver)&precond);
6596 if (HYPRE_AssumedPartitionCheck())
6600 MPI_Scan(&locSize, &part[1], 1, HYPRE_MPI_BIG_INT, MPI_SUM, comm);
6602 part[0] = part[1] - locSize;
6604 MPI_Allreduce(&locSize, &glbSize, 1, HYPRE_MPI_BIG_INT, MPI_SUM, comm);
6610 MPI_Allgather(&locSize, 1, HYPRE_MPI_BIG_INT,
6611 &part[1], 1, HYPRE_MPI_BIG_INT, comm);
6614 for (
int i=0; i<numProcs; i++)
6616 part[i+1] += part[i];
6619 glbSize = part[numProcs];
6631 matvec_fn.MatvecCreate = this->OperatorMatvecCreate;
6632 matvec_fn.Matvec = this->OperatorMatvec;
6633 matvec_fn.MatvecDestroy = this->OperatorMatvecDestroy;
6635 HYPRE_LOBPCGSetup(lobpcg_solver,(HYPRE_Matrix)&A,NULL,NULL);
6641 matvec_fn.MatvecCreate = this->OperatorMatvecCreate;
6642 matvec_fn.Matvec = this->OperatorMatvec;
6643 matvec_fn.MatvecDestroy = this->OperatorMatvecDestroy;
6645 HYPRE_LOBPCGSetupB(lobpcg_solver,(HYPRE_Matrix)&M,NULL);
6654 for (
int i=0; i<nev; i++)
6656 eigs[i] = eigenvalues[i];
6663 return multi_vec->GetVector(i);
6670 if ( multi_vec == NULL )
6672 MFEM_ASSERT(x != NULL,
"In HypreLOBPCG::SetInitialVectors()");
6674 multi_vec =
new HypreMultiVector(nev, *x, interpreter);
6678 for (
int i=0; i < min(num_vecs,nev); i++)
6680 multi_vec->GetVector(i) = *vecs[i];
6684 for (
int i=min(num_vecs,nev); i < nev; i++)
6686 multi_vec->GetVector(i).
Randomize(seed);
6690 if ( subSpaceProj != NULL )
6693 y = multi_vec->GetVector(0);
6695 for (
int i=1; i<nev; i++)
6697 subSpaceProj->
Mult(multi_vec->GetVector(i),
6698 multi_vec->GetVector(i-1));
6700 subSpaceProj->
Mult(y,
6701 multi_vec->GetVector(nev-1));
6709 if ( multi_vec == NULL )
6711 MFEM_ASSERT(x != NULL,
"In HypreLOBPCG::Solve()");
6713 multi_vec =
new HypreMultiVector(nev, *x, interpreter);
6714 multi_vec->Randomize(seed);
6716 if ( subSpaceProj != NULL )
6719 y = multi_vec->GetVector(0);
6721 for (
int i=1; i<nev; i++)
6723 subSpaceProj->
Mult(multi_vec->GetVector(i),
6724 multi_vec->GetVector(i-1));
6726 subSpaceProj->
Mult(y, multi_vec->GetVector(nev-1));
6737 HYPRE_LOBPCGSolve(lobpcg_solver, NULL, *multi_vec, eigenvalues);
6741HypreLOBPCG::OperatorMatvecCreate(
void *A,
6748 return ( matvec_data );
6752HypreLOBPCG::OperatorMatvec(
void *matvec_data,
6753 HYPRE_Complex
alpha,
6759 MFEM_VERIFY(
alpha == 1.0 && beta == 0.0,
"values not supported");
6761 Operator *Aop = (Operator*)A;
6763 hypre_ParVector * xPar = (hypre_ParVector *)x;
6764 hypre_ParVector * yPar = (hypre_ParVector *)y;
6766 HypreParVector xVec(xPar);
6767 HypreParVector yVec(yPar);
6769 Aop->Mult( xVec, yVec );
6773 yVec.HypreReadWrite();
6779HypreLOBPCG::OperatorMatvecDestroy(
void *matvec_data )
6785HypreLOBPCG::PrecondSolve(
void *solver,
6790 Solver *
PC = (Solver*)solver;
6792 hypre_ParVector * bPar = (hypre_ParVector *)
b;
6793 hypre_ParVector * xPar = (hypre_ParVector *)x;
6795 HypreParVector bVec(bPar);
6796 HypreParVector xVec(xPar);
6798 PC->Mult( bVec, xVec );
6802 xVec.HypreReadWrite();
6808HypreLOBPCG::PrecondSetup(
void *solver,
6826 MPI_Comm_size(comm,&numProcs);
6827 MPI_Comm_rank(comm,&myid);
6829 HYPRE_AMECreate(&ame_solver);
6830 HYPRE_AMESetPrintLevel(ame_solver, 0);
6837 mfem_hypre_TFree_host(multi_vec);
6842 for (
int i=0; i<nev; i++)
6844 delete eigenvectors[i];
6847 delete [] eigenvectors;
6851 mfem_hypre_TFree_host(eigenvalues);
6854 HYPRE_AMEDestroy(ame_solver);
6862 HYPRE_AMESetBlockSize(ame_solver, nev);
6868 HYPRE_AMESetTol(ame_solver, tol);
6874#if MFEM_HYPRE_VERSION >= 21101
6875 HYPRE_AMESetRTol(ame_solver, rel_tol);
6877 MFEM_ABORT(
"This method requires HYPRE version >= 2.11.1");
6884 HYPRE_AMESetMaxIter(ame_solver, max_iter);
6892 HYPRE_AMESetPrintLevel(ame_solver, logging);
6899 ams_precond = &precond;
6907 HYPRE_Solver ams_precond_ptr = (HYPRE_Solver)*ams_precond;
6909 ams_precond->
SetupFcn()(*ams_precond,A,NULL,NULL);
6911 HYPRE_AMESetAMSSolver(ame_solver, ams_precond_ptr);
6914 HYPRE_AMESetup(ame_solver);
6920 HYPRE_ParCSRMatrix parcsr_M = M;
6921 HYPRE_AMESetMassMatrix(ame_solver,(HYPRE_ParCSRMatrix)parcsr_M);
6927 HYPRE_AMESolve(ame_solver);
6930 HYPRE_AMEGetEigenvalues(ame_solver,&eigenvalues);
6933 HYPRE_AMEGetEigenvectors(ame_solver,&multi_vec);
6940 eigs.
SetSize(nev); eigs = -1.0;
6943 for (
int i=0; i<nev; i++)
6945 eigs[i] = eigenvalues[i];
6950HypreAME::createDummyVectors()
const
6953 for (
int i=0; i<nev; i++)
6960const HypreParVector &
6963 if ( eigenvectors == NULL )
6965 this->createDummyVectors();
6968 return *eigenvectors[i];
6974 if ( eigenvectors == NULL )
6976 this->createDummyVectors();
6981 eigenvectors = NULL;
Dynamic 2D array using row-major layout.
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
T * GetData()
Returns the data.
static MemoryType GetHostMemoryType()
Get the current Host MemoryType. This is the MemoryType used by most MFEM classes when allocating mem...
static MemoryClass GetHostMemoryClass()
Get the current Host MemoryClass. This is the MemoryClass used by most MFEM host Memory objects.
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
int GetRangeDim(int dim) const
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Ordering::Type GetOrdering() const
Return the ordering method.
const FiniteElementCollection * FEColl() const
Hash function for data sequences.
std::string GetHash() const
Return the hash string for the current sequence and reset (clear) the sequence.
HashFunction & AppendDoubles(const real_t *doubles, size_t num_doubles)
Add a sequence of doubles for hashing, given as a c-array.
HashFunction & AppendInts(const int_type *ints, size_t num_ints)
Add a sequence of integers for hashing, given as a c-array.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
HypreADS(ParFiniteElementSpace *face_fespace)
void SetPrintLevel(int print_lvl)
void SetNumModes(int num_eigs)
void SetPreconditioner(HypreSolver &precond)
void SetPrintLevel(int logging)
void SetMassMatrix(const HypreParMatrix &M)
const HypreParVector & GetEigenvector(unsigned int i) const
Extract a single eigenvector.
void GetEigenvalues(Array< real_t > &eigenvalues) const
Collect the converged eigenvalues.
void SetOperator(const HypreParMatrix &A)
void Solve()
Solve the eigenproblem.
void SetMaxIter(int max_iter)
HypreParVector ** StealEigenvectors()
Transfer ownership of the converged eigenvectors.
void SetRelTol(real_t rel_tol)
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
HypreAMS(ParFiniteElementSpace *edge_fespace)
Construct the AMS solver on the given edge finite element space.
void SetPrintLevel(int print_lvl)
void SetSystemsOptions(int dim, bool order_bynodes=false)
void SetElasticityOptions(ParFiniteElementSpace *fespace, bool interp_refine=true)
void SetAdvectiveOptions(int distance=15, const std::string &prerelax="", const std::string &postrelax="FFC")
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
virtual ~HypreBoomerAMG()
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
HypreEuclid(MPI_Comm comm)
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void SetRowScale(int row_scale)
void SetMaxIter(int max_iter)
void GetFinalAbsResidualNorm(real_t &final_res_norm, real_t p=2) const
Computes the absolute residual p-norm.
HypreFGMRES(MPI_Comm comm)
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
HypreParVector GetResiduals() const
void SetPrintLevel(int print_lvl)
void Mult(const HypreParVector &b, HypreParVector &x) const override
Solve Ax=b with hypre's FGMRES.
void SetLogging(int logging)
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
HypreParVector GetResiduals() const
void SetLogging(int logging)
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
void GetFinalAbsResidualNorm(real_t &final_res_norm, real_t p=2) const
Computes the absolute residual p-norm.
void SetMaxIter(int max_iter)
void SetPrintLevel(int print_lvl)
void Mult(const HypreParVector &b, HypreParVector &x) const override
Solve Ax=b with hypre's GMRES.
HypreGMRES(MPI_Comm comm)
void SetAbsTol(real_t tol)
HypreILU()
Constructor; sets the default options.
void SetType(HYPRE_Int ilu_type)
void SetLocalReordering(HYPRE_Int reorder_type)
void SetMaxIter(HYPRE_Int max_iter)
void SetLevelOfFill(HYPRE_Int lev_fill)
Set the fill level for ILU(k); the default is k=1.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void SetTol(HYPRE_Real tol)
void SetPrintLevel(HYPRE_Int print_level)
Set the print level: 0 = none, 1 = setup, 2 = solve, 3 = setup+solve.
void SetMassMatrix(Operator &M)
HypreLOBPCG(MPI_Comm comm)
void SetPrintLevel(int logging)
void SetPreconditioner(Solver &precond)
void GetEigenvalues(Array< real_t > &eigenvalues) const
Collect the converged eigenvalues.
void SetOperator(Operator &A)
void Solve()
Solve the eigenproblem.
void SetPrecondUsageMode(int pcg_mode)
void SetInitialVectors(int num_vecs, HypreParVector **vecs)
void SetMaxIter(int max_iter)
void SetRelTol(real_t rel_tol)
const HypreParVector & GetEigenvector(unsigned int i) const
Extract a single eigenvector.
void Mult(const HypreParVector &b, HypreParVector &x) const override
Solve Ax=b with hypre's PCG.
bool GetUseTwoNorm() const
void SetResidualConvergenceOptions(int res_frequency=-1, real_t rtol=0.0)
void SetPrintLevel(int print_lvl)
void SetLogging(int logging)
void SetUseTwoNorm(bool use)
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
void SetMaxIter(int max_iter)
HypreParVector GetResiduals() const
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void SetAbsTol(real_t atol)
void GetFinalAbsResidualNorm(real_t &final_res_norm, real_t p=2) const
Computes the absolute residual p-norm.
Wrapper for hypre's ParCSR matrix class.
void HypreReadWrite()
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
void operator*=(real_t s)
Scale all entries by s: A_scaled = s*A.
signed char OwnsColMap() const
Get colmap ownership flag.
HYPRE_BigInt N() const
Returns the global number of columns.
void ScaleRows(const Vector &s)
Scale the local row i by s(i).
void AbsMultTranspose(real_t a, const Vector &x, real_t b, Vector &y) const
Computes y = a * |At| * x + b * y, using entry-wise absolute values of the transpose of the matrix A.
void HostReadWrite()
Update the internal hypre_ParCSRMatrix object, A, to be on host.
void Print(const std::string &fname, HYPRE_Int offi=0, HYPRE_Int offj=0) const
Prints the locally owned rows in parallel. The resulting files can be read with Read_IJMatrix().
void DropSmallEntries(real_t tol)
Wrapper for hypre_ParCSRMatrixDropSmallEntries in different versions of hypre. Drop off-diagonal entr...
void PrintCommPkg(std::ostream &out=mfem::out) const
Print information about the hypre_ParCSRCommPkg of the HypreParMatrix.
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, real_t alpha=1.0, real_t beta=0.0) const
Computes y = alpha * A^t * x + beta * y.
void Threshold(real_t threshold=0.0)
Remove values smaller in absolute value than some threshold.
Memory< HYPRE_Int > & GetDiagMemoryI()
HypreParMatrix * LeftDiagMult(const SparseMatrix &D, HYPRE_BigInt *row_starts=NULL) const
Multiply the HypreParMatrix on the left by a block-diagonal parallel matrix D and return the result a...
void EliminateRows(const Array< int > &rows)
Eliminate rows from the diagonal and off-diagonal blocks of the matrix.
void AbsMult(real_t a, const Vector &x, real_t b, Vector &y) const
Computes y = a * |A| * x + b * y, using entry-wise absolute values of the matrix A.
int GetNumCols() const
Returns the number of columns in the diagonal block of the ParCSRMatrix.
void SetOwnerFlags(signed char diag, signed char offd, signed char colmap)
Explicitly set the three ownership flags, see docs for diagOwner etc.
void InvScaleRows(const Vector &s)
Scale the local row i by 1./s(i)
void ResetTranspose() const
Reset (destroy) the internal transpose matrix that is created by EnsureMultTranspose() and MultTransp...
void WrapHypreParCSRMatrix(hypre_ParCSRMatrix *a, bool owner=true)
Converts hypre's format to HypreParMatrix.
int GetNumRows() const
Returns the number of rows in the diagonal block of the ParCSRMatrix.
Memory< HYPRE_Int > & GetDiagMemoryJ()
HYPRE_BigInt * GetRowStarts() const
Return the parallel row partitioning array.
void HypreRead() const
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
HypreParMatrix()
An empty matrix to be used as a reference to an existing matrix.
signed char OwnsOffd() const
Get offd ownership flag.
HYPRE_BigInt GetGlobalNumRows() const
Return the global number of rows.
void PrintHash(std::ostream &out) const
Print sizes and hashes for all data arrays of the HypreParMatrix from the local MPI rank.
void HostWrite()
Update the internal hypre_ParCSRMatrix object, A, to be on host.
HYPRE_BigInt GetGlobalNumCols() const
Return the global number of columns.
void HostRead() const
Update the internal hypre_ParCSRMatrix object, A, to be on host.
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, real_t alpha=1.0, real_t beta=0.0) const
Computes y = alpha * A * x + beta * y.
HypreParMatrix * ExtractSubmatrix(const Array< int > &indices, real_t threshold=0.0) const
void EnsureMultTranspose() const
Ensure the action of the transpose is performed fast.
MPI_Comm GetComm() const
MPI communicator.
Memory< real_t > & GetDiagMemoryData()
HYPRE_BigInt * GetColStarts() const
Return the parallel column partitioning array.
void GetOffdColMap(HYPRE_BigInt *&cmap, HYPRE_Int &num_cols) const
Get the global column mapping for the local off-diagonal block.
void Read_IJMatrix(MPI_Comm comm, const std::string &fname)
Read a matrix saved as a HYPRE_IJMatrix.
HypreParMatrix & Add(const real_t beta, const HypreParMatrix &B)
void GetBlocks(Array2D< HypreParMatrix * > &blocks, bool interleaved_rows=false, bool interleaved_cols=false) const
void EliminateBC(const HypreParMatrix &Ae, const Array< int > &ess_dof_list, const Vector &X, Vector &B) const
Eliminate essential BC specified by ess_dof_list from the solution X to the r.h.s....
void MakeRef(const HypreParMatrix &master)
Make this HypreParMatrix a reference to 'master'.
real_t FNorm() const
Return the Frobenius norm of the matrix (or 0 if the underlying hypre matrix is NULL)
void GetOffd(SparseMatrix &offd, HYPRE_BigInt *&cmap) const
Get the local off-diagonal block. NOTE: 'offd' will not own any data.
HYPRE_BigInt M() const
Returns the global number of rows.
hypre_ParCSRMatrix * StealData()
Changes the ownership of the matrix.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
void MergeDiagAndOffd(SparseMatrix &merged)
Get a single SparseMatrix containing all rows from this processor, merged from the diagonal and off-d...
HypreParMatrix * EliminateCols(const Array< int > &cols)
Wrapper for hypre's parallel vector class.
void WrapMemoryWrite(Memory< real_t > &mem)
Replace the HypreParVector's data with the given Memory, mem, and prepare the vector for write access...
void HypreRead() const
Prepare the HypreParVector for read access in hypre's device memory space, HYPRE_MEMORY_DEVICE.
void Read(MPI_Comm comm, const std::string &fname)
Reads a HypreParVector from files saved with HypreParVector::Print.
HypreParVector CreateCompatibleVector() const
Constructs a HypreParVector compatible with the calling vector.
void Print(const std::string &fname) const
Prints the locally owned rows in parallel.
void WrapMemoryReadWrite(Memory< real_t > &mem)
Replace the HypreParVector's data with the given Memory, mem, and prepare the vector for read and wri...
~HypreParVector()
Calls hypre's destroy function.
void WrapHypreParVector(hypre_ParVector *y, bool owner=true)
Converts hypre's format to HypreParVector.
HYPRE_Int Randomize(HYPRE_Int seed)
Set random values.
void HypreReadWrite()
Prepare the HypreParVector for read and write access in hypre's device memory space,...
void HypreWrite()
Prepare the HypreParVector for write access in hypre's device memory space, HYPRE_MEMORY_DEVICE.
HypreParVector()
Default constructor, no underlying hypre_ParVector is created.
void WrapMemoryRead(const Memory< real_t > &mem)
Replace the HypreParVector's data with the given Memory, mem, and prepare the vector for read access ...
HypreParVector & operator=(real_t d)
Set constant values.
void SetData(real_t *data_)
Sets the data of the Vector and the hypre_ParVector to data_.
Vector * GlobalVector() const
Returns the global vector in each processor.
void SetOwnership(int own)
Sets ownership of the internal hypre_ParVector.
void SetReuse(int reuse)
Set the pattern reuse parameter.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void SetSymmetry(int sym)
Set symmetry parameter.
void SetParams(real_t thresh, int nlevels)
Set the threshold and levels parameters.
void SetLoadBal(real_t loadbal)
Set the load balance parameter.
HypreParaSails(MPI_Comm comm)
void SetFilter(real_t filter)
Set the filter parameter.
void SetLogging(int logging)
Set the logging parameter.
virtual ~HypreParaSails()
int eig_est_cg_iter
Number of CG iterations to determine eigenvalue estimates.
int poly_order
Order of the smoothing polynomial.
void GetSOROptions(real_t &relax_weight, real_t &omega) const
void SetPolyOptions(int poly_order, real_t poly_fraction, int eig_est_cg_iter=10)
Set parameters for polynomial smoothing.
void SetFIRCoefficients(real_t max_eig)
Compute window and Chebyshev coefficients for given polynomial order.
void SetWindowParameters(real_t a, real_t b, real_t c)
Set parameters for windowing function for FIR smoother.
real_t poly_fraction
Fraction of spectrum to smooth for polynomial relaxation.
void MultTranspose(const Vector &b, Vector &x) const override
Apply transpose of the smoother to relax the linear system Ax=b.
HypreParVector * V
Temporary vectors.
HypreParMatrix * A
The linear system matrix.
real_t * fir_coeffs
Combined coefficients for windowing and Chebyshev polynomials.
int relax_times
Number of relaxation sweeps.
void SetWindowByName(const char *window_name)
Convenience function for setting canonical windowing parameters.
void GetWindowParameters(real_t &a, real_t &b, real_t &c) const
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Relax the linear system Ax=b.
void GetTaubinOptions(real_t &lambda, real_t &mu, int &iter) const
real_t * l1_norms
l1 norms of the rows of A
void GetPolyOptions(int &poly_order, real_t &poly_fraction, int &eig_est_cg_iter) const
void SetOperator(const Operator &op) override
real_t max_eig_est
Maximal eigenvalue estimate for polynomial smoothing.
void SetTaubinOptions(real_t lambda, real_t mu, int iter)
Set parameters for Taubin's lambda-mu method.
bool pos_l1_norms
If set, take absolute values of the computed l1_norms.
real_t window_params[3]
Parameters for windowing function of FIR filter.
real_t omega
SOR parameter (usually in (0,2))
int poly_scale
Apply the polynomial smoother to A or D^{-1/2} A D^{-1/2}.
HypreParVector * B
Right-hand side and solution vectors.
real_t relax_weight
Damping coefficient (usually <= 1)
real_t min_eig_est
Minimal eigenvalue estimate for polynomial smoothing.
void SetSOROptions(real_t relax_weight, real_t omega)
Set SOR-related parameters.
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
Type
HYPRE smoother types.
real_t lambda
Taubin's lambda-mu method parameters.
Type GetType() const
Return the type ID of the Operator class.
Memory< real_t > auxB
Auxiliary buffers for the case when the input or output arrays in methods like Mult(const Vector &,...
bool A_is_symmetric
A flag that indicates whether the linear system matrix A is symmetric.
HypreParVector * X0
FIR Filter Temporary Vectors.
static Type DefaultType()
Default value for the smoother type used by the constructors: Type::l1GS when HYPRE is running on CPU...
Abstract class for hypre's solvers and preconditioners.
const HypreParMatrix * A
The linear system matrix.
int setup_called
Was hypre's Setup function called already?
@ WARN_HYPRE_ERRORS
Issue warnings on hypre errors.
@ IGNORE_HYPRE_ERRORS
Ignore hypre errors (see e.g. HypreADS)
@ ABORT_HYPRE_ERRORS
Abort on hypre errors (default in base class)
virtual HYPRE_PtrToParSolverFcn SolveFcn() const =0
hypre's internal Solve function
HypreParVector * B
Right-hand side and solution vector.
bool WrapVectors(const Vector &b, Vector &x) const
Makes the internal HypreParVectors B and X wrap the input vectors b and x.
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Solve the linear system Ax=b.
ErrorMode error_mode
How to treat hypre errors.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
virtual void Setup(const HypreParVector &b, HypreParVector &x) const
Set up the solver (if not set up already, also called automatically by HypreSolver::Mult).
virtual HYPRE_PtrToParSolverFcn SetupFcn() const =0
hypre's internal Setup function
static void InitDevice()
Configure HYPRE's compute and memory policy.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
static bool configure_runtime_policy_from_mfem
Use MFEM's device policy to configure HYPRE's device policy, true by default. This variable is used b...
static void Finalize()
Finalize hypre (called automatically at program exit if Hypre::Init() has been called).
A class to initialize the size of a Tensor.
static MemoryType GetDualMemoryType(MemoryType mt)
Return the dual MemoryType of the given one, mt.
Class used by MFEM to store pointers to host and/or device memory.
void SetHostPtrOwner(bool own) const
Set/clear the ownership flag for the host pointer. Ownership indicates whether the pointer will be de...
T * Write(MemoryClass mc, int size)
Get write-only access to the memory with the given MemoryClass.
MemoryType GetHostMemoryType() const
Return the host MemoryType of the Memory object.
void SetDevicePtrOwner(bool own) const
Set/clear the ownership flag for the device pointer. Ownership indicates whether the pointer will be ...
int Capacity() const
Return the size of the allocated memory.
MemoryType GetDeviceMemoryType() const
Return the device MemoryType of the Memory object. If the device MemoryType is not set,...
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
void MakeAlias(const Memory &base, int offset, int size)
Create a memory object that points inside the memory object base.
bool OwnsHostPtr() const
Return true if the host pointer is owned. Ownership indicates whether the pointer will be deleted by ...
bool Empty() const
Return true if the Memory object is empty, see Reset().
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
void Wrap(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with the current host memory type returned by MemoryMa...
void Delete()
Delete the owned pointers and reset the Memory object.
void ClearOwnerFlags() const
Clear the ownership flags for the host and device pointers, as well as any internal data allocated by...
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
int Dimension() const
Dimension of the reference space used within the elements.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces,...
int width
Dimension of the input / number of columns in the matrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
DiagonalPolicy
Defines operator diagonal policy upon elimination of rows and/or columns.
@ DIAG_ONE
Set the diagonal value to one.
@ DIAG_ZERO
Set the diagonal value to zero.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
Abstract parallel finite element space.
HYPRE_BigInt * GetTrueDofOffsets() const
HYPRE_BigInt GlobalTrueVSize() const
HypreParVector * NewTrueDofVector()
ParMesh * GetParMesh() const
Class for parallel meshes.
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
int NumNonZeroElems() const override
Returns the number of the nonzero elements in the matrix.
Memory< int > & GetMemoryI()
void Swap(SparseMatrix &other)
void Clear()
Clear the contents of the SparseMatrix.
Memory< int > & GetMemoryJ()
Memory< real_t > & GetMemoryData()
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
int Size() const
Returns the number of TYPE I elements.
int Size_of_connections() const
Returns the number of connections in the table.
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
real_t Normlinf() const
Returns the l_infinity norm of the vector.
void MakeDataOwner() const
Set the Vector data (host pointer) ownership flag.
real_t Norml1() const
Returns the l_1 norm of the vector.
Memory< real_t > & GetMemory()
Return a reference to the Memory object used by the Vector.
real_t Norml2() const
Returns the l2 norm of the vector.
void Destroy()
Destroy a vector.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
Vector & operator=(const real_t *v)
Copy Size() entries from v.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
real_t sigma(const Vector &x)
MemoryType GetHypreMemoryType()
The MemoryType used by MFEM when allocating arrays for Hypre objects.
void CopyMemory(Memory< T > &src, Memory< T > &dst, MemoryClass dst_mc, bool dst_owner)
Shallow or deep copy src to dst with the goal to make the array src accessible through dst with the M...
bool CanShallowCopy(const Memory< T > &src, MemoryClass mc)
Return true if the src Memory can be used with the MemoryClass mc.
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
MemoryClass GetHypreForallMemoryClass()
real_t ParNormlp(const Vector &vec, real_t p, MPI_Comm comm)
Compute the l_p norm of the Vector which is split without overlap across the given communicator.
real_t u(const Vector &xvec)
void mfem_error(const char *msg)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
decltype(hypre_CSRMatrix::memory_location) GetHypreParMatrixMemoryLocation(MemoryClass mc)
const T * HostRead(const Memory< T > &mem, int size)
Shortcut to Read(const Memory<T> &mem, int size, false)
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
real_t InnerProduct(HypreParVector *x, HypreParVector *y)
MemoryClass
Memory classes identify sets of memory types.
MemoryClass GetHypreMemoryClass()
The MemoryClass used by Hypre objects.
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
int ParCSRRelax_FIR(hypre_ParCSRMatrix *A, hypre_ParVector *f, real_t max_eig, int poly_order, real_t *fir_coeffs, hypre_ParVector *u, hypre_ParVector *x0, hypre_ParVector *x1, hypre_ParVector *x2, hypre_ParVector *x3)
void delete_hypre_ParCSRMatrixColMapOffd(hypre_ParCSRMatrix *A)
HypreParMatrix * HypreParMatrixFromBlocks(Array2D< const HypreParMatrix * > &blocks, Array2D< real_t > *blockCoeff)
Returns a merged hypre matrix constructed from hypre matrix blocks.
HypreParMatrix * ParAdd(const HypreParMatrix *A, const HypreParMatrix *B)
Returns the matrix A + B.
T * HostWrite(Memory< T > &mem, int size)
Shortcut to Write(const Memory<T> &mem, int size, false)
int ParCSRRelax_Taubin(hypre_ParCSRMatrix *A, hypre_ParVector *f, real_t lambda, real_t mu, int N, real_t max_eig, hypre_ParVector *u, hypre_ParVector *r)
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
void GatherBlockOffsetData(MPI_Comm comm, const int rank, const int nprocs, const int num_loc, const Array< int > &offsets, std::vector< int > &all_num_loc, const int numBlocks, std::vector< std::vector< HYPRE_BigInt > > &blockProcOffsets, std::vector< HYPRE_BigInt > &procOffsets, std::vector< std::vector< int > > &procBlockOffsets, HYPRE_BigInt &firstLocal, HYPRE_BigInt &globalNum)
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
void CopyConvertMemory(const Memory< SrcT > &src, MemoryClass dst_mc, Memory< DstT > &dst)
Deep copy and convert src to dst with the goal to make the array src accessible through dst with the ...
void hypre_forall(int N, lambda &&body)
bool HypreUsingGPU()
Return true if HYPRE is configured to use GPU.
void BlockInverseScale(const HypreParMatrix *A, HypreParMatrix *C, const Vector *b, HypreParVector *d, int blocksize, BlockInverseScaleJob job)
MemoryType
Memory types supported by MFEM.
@ HOST
Host memory; using new[] and delete[].
void EliminateBC(const HypreParMatrix &A, const HypreParMatrix &Ae, const Array< int > &ess_dof_list, const Vector &X, Vector &B)
Eliminate essential BC specified by ess_dof_list from the solution X to the r.h.s....
HYPRE_MemoryLocation GetHypreMemoryLocation()
Return the configured HYPRE_MemoryLocation.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
bool MemoryClassContainsType(MemoryClass mc, MemoryType mt)
Return true iff the MemoryType mt is contained in the MemoryClass mc.
void forall(int N, lambda &&body)
constexpr real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE real_t norm(const Complex &z)
@ DEBUG_DEVICE
[device] Debug backend: host memory is READ/WRITE protected while a device is in use....
@ DEVICE_MASK
Biwise-OR of all device backends.
Helper struct to convert a C++ type to an MPI type.