23#if defined(PETSC_HAVE_HYPRE)
24#include "petscmathypre.h"
28#if PETSC_VERSION_LT(3,11,0)
29#define VecLockReadPush VecLockPush
30#define VecLockReadPop VecLockPop
32#if PETSC_VERSION_LT(3,12,0)
33#define VecGetArrayWrite VecGetArray
34#define VecRestoreArrayWrite VecRestoreArray
35#define MatComputeOperator(A,B,C) MatComputeExplicitOperator(A,C)
36#define MatComputeOperatorTranspose(A,B,C) MatComputeExplicitOperatorTranspose(A,C)
38#if PETSC_VERSION_LT(3,19,0)
39#define PETSC_SUCCESS 0
53static PetscErrorCode __mfem_ts_rhsfunction(TS,
PetscReal,Vec,Vec,
void*);
54static PetscErrorCode __mfem_ts_rhsjacobian(TS,
PetscReal,Vec,Mat,Mat,
56static PetscErrorCode __mfem_ts_ifunction(TS,
PetscReal,Vec,Vec,Vec,
void*);
57static PetscErrorCode __mfem_ts_ijacobian(TS,
PetscReal,Vec,Vec,
60static PetscErrorCode __mfem_ts_computesplits(TS,
PetscReal,Vec,Vec,
63static PetscErrorCode __mfem_snes_jacobian(SNES,Vec,Mat,Mat,
void*);
64static PetscErrorCode __mfem_snes_function(SNES,Vec,Vec,
void*);
65static PetscErrorCode __mfem_snes_objective(SNES,Vec,
PetscReal*,
void*);
66static PetscErrorCode __mfem_snes_update(SNES,
PetscInt);
67static PetscErrorCode __mfem_snes_postcheck(SNESLineSearch,Vec,Vec,Vec,
68 PetscBool*,PetscBool*,
void*);
70static PetscErrorCode __mfem_pc_shell_apply(PC,Vec,Vec);
71static PetscErrorCode __mfem_pc_shell_apply_transpose(PC,Vec,Vec);
72static PetscErrorCode __mfem_pc_shell_setup(PC);
73static PetscErrorCode __mfem_pc_shell_destroy(PC);
74static PetscErrorCode __mfem_pc_shell_view(PC,PetscViewer);
75static PetscErrorCode __mfem_mat_shell_apply(Mat,Vec,Vec);
76static PetscErrorCode __mfem_mat_shell_apply_transpose(Mat,Vec,Vec);
77static PetscErrorCode __mfem_mat_shell_destroy(Mat);
78static PetscErrorCode __mfem_mat_shell_copy(Mat,Mat,MatStructure);
79#if PETSC_VERSION_LT(3,23,0)
80static PetscErrorCode __mfem_array_container_destroy(
void*);
81static PetscErrorCode __mfem_matarray_container_destroy(
void *);
83static PetscErrorCode __mfem_array_container_destroy(
void**);
84static PetscErrorCode __mfem_matarray_container_destroy(
void**);
86static PetscErrorCode __mfem_monitor_ctx_destroy(
void**);
94static PetscErrorCode MakeShellPCWithFactory(PC,
100#if !defined(PETSC_HAVE_HYPRE)
101static PetscErrorCode MatConvert_hypreParCSR_AIJ(hypre_ParCSRMatrix*,Mat*);
102static PetscErrorCode MatConvert_hypreParCSR_IS(hypre_ParCSRMatrix*,Mat*);
105#if PETSC_VERSION_GE(3,15,0) && defined(PETSC_HAVE_DEVICE)
106#if defined(MFEM_USE_CUDA) && defined(PETSC_HAVE_CUDA)
108#define PETSC_VECDEVICE VECCUDA
109#define PETSC_MATAIJDEVICE MATAIJCUSPARSE
110#define VecDeviceGetArrayRead VecCUDAGetArrayRead
111#define VecDeviceGetArrayWrite VecCUDAGetArrayWrite
112#define VecDeviceGetArray VecCUDAGetArray
113#define VecDeviceRestoreArrayRead VecCUDARestoreArrayRead
114#define VecDeviceRestoreArrayWrite VecCUDARestoreArrayWrite
115#define VecDeviceRestoreArray VecCUDARestoreArray
116#define VecDevicePlaceArray VecCUDAPlaceArray
117#define VecDeviceResetArray VecCUDAResetArray
118#elif defined(MFEM_USE_HIP) && defined(PETSC_HAVE_HIP)
120#define PETSC_VECDEVICE VECHIP
121#define PETSC_MATAIJDEVICE MATAIJHIPSPARSE
122#define VecDeviceGetArrayRead VecHIPGetArrayRead
123#define VecDeviceGetArrayWrite VecHIPGetArrayWrite
124#define VecDeviceGetArray VecHIPGetArray
125#define VecDeviceRestoreArrayRead VecHIPRestoreArrayRead
126#define VecDeviceRestoreArrayWrite VecHIPRestoreArrayWrite
127#define VecDeviceRestoreArray VecHIPRestoreArray
128#define VecDevicePlaceArray VecHIPPlaceArray
129#define VecDeviceResetArray VecHIPResetArray
131#define VecDeviceGetArrayRead VecGetArrayRead
132#define VecDeviceGetArrayWrite VecGetArrayWrite
133#define VecDeviceGetArray VecGetArray
134#define VecDeviceRestoreArrayRead VecRestoreArrayRead
135#define VecDeviceRestoreArrayWrite VecRestoreArrayWrite
136#define VecDeviceRestoreArray VecRestoreArray
137#define VecDevicePlaceArray VecPlaceArray
138#define VecDeviceResetArray VecResetArray
142#if defined(PETSC_HAVE_DEVICE)
143static PetscErrorCode __mfem_VecSetOffloadMask(Vec,PetscOffloadMask);
145static PetscErrorCode __mfem_VecBoundToCPU(Vec,PetscBool*);
146static PetscErrorCode __mfem_PetscObjectStateIncrease(
PetscObject);
147static PetscErrorCode __mfem_MatCreateDummy(MPI_Comm,
PetscInt,
PetscInt,Mat*);
155 unsigned long int numprec;
156} __mfem_pc_shell_ctx;
185 PetscObjectState cached_ijacstate;
186 PetscObjectState cached_rhsjacstate;
187 PetscObjectState cached_splits_xstate;
188 PetscObjectState cached_splits_xdotstate;
198static PetscErrorCode ierr;
199static PetscMPIInt mpiierr;
222#if PETSC_VERSION_LT(3,17,0)
223 const char *opts =
"-cuda_device";
225 const char *opts =
"-device_select_cuda";
227 ierr = PetscOptionsSetValue(NULL,opts,
229 MFEM_VERIFY(!ierr,
"Unable to set initial option value to PETSc");
233#if PETSC_VERSION_LT(3,17,0)
234 const char *opts =
"-hip_device";
236 const char *opts =
"-device_select_hip";
238 ierr = PetscOptionsSetValue(NULL,opts,
240 MFEM_VERIFY(!ierr,
"Unable to set initial option value to PETSc");
242 ierr = PetscInitialize(argc,argv,rc_file,help);
243 MFEM_VERIFY(!ierr,
"Unable to initialize PETSc");
248 ierr = PetscFinalize();
249 MFEM_VERIFY(!ierr,
"Unable to finalize PETSc");
278 MFEM_VERIFY(
x,
"Missing Vec");
279 ierr = VecSetUp(
x); PCHKERRQ(
x,ierr);
280 ierr = PetscObjectTypeCompare((
PetscObject)
x,VECNEST,&isnest); PCHKERRQ(
x,ierr);
281 MFEM_VERIFY(!isnest,
"Not for type nest");
282 ierr = VecGetLocalSize(
x,&n); PCHKERRQ(
x,ierr);
283 MFEM_VERIFY(n >= 0,
"Invalid local size");
285#if defined(PETSC_HAVE_DEVICE)
286 PetscOffloadMask omask;
289 ierr = VecGetOffloadMask(
x,&omask); PCHKERRQ(
x,ierr);
290 if (omask != PETSC_OFFLOAD_BOTH)
292 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_CPU); PCHKERRQ(
x,ierr);
295 ierr = VecGetArrayRead(
x,(
const PetscScalar**)&array); PCHKERRQ(
x,ierr);
296#if defined(PETSC_HAVE_DEVICE)
297 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
298 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
299 ""); PCHKERRQ(
x,ierr);
302 if (omask != PETSC_OFFLOAD_BOTH)
304 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_GPU); PCHKERRQ(
x,ierr);
307 ierr = VecDeviceGetArrayRead(
x,(
const PetscScalar**)&darray);
310 ierr = VecDeviceRestoreArrayRead(
x,(
const PetscScalar**)&darray);
318 ierr = VecRestoreArrayRead(
x,(
const PetscScalar**)&array); PCHKERRQ(
x,ierr);
320#if defined(PETSC_HAVE_DEVICE)
321 if (omask == PETSC_OFFLOAD_UNALLOCATED && isdevice) { omask = PETSC_OFFLOAD_CPU; }
322 ierr = __mfem_VecSetOffloadMask(
x,omask); PCHKERRQ(
x,ierr);
330 MFEM_VERIFY(
x,
"Missing Vec");
331#if defined(_USE_DEVICE)
332 PetscOffloadMask mask;
334 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
335 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
336 ""); PCHKERRQ(
x,ierr);
337 ierr = VecGetOffloadMask(
x,&mask); PCHKERRQ(
x,ierr);
342 case PETSC_OFFLOAD_CPU:
346 case PETSC_OFFLOAD_GPU:
350 case PETSC_OFFLOAD_BOTH:
355 MFEM_ABORT(
"Unhandled case " << mask);
364 MFEM_VERIFY(
x,
"Missing Vec");
365 ierr = __mfem_PetscObjectStateIncrease((
PetscObject)
x); PCHKERRQ(
x,ierr);
366#if defined(_USE_DEVICE)
368 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
369 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
370 ""); PCHKERRQ(
x,ierr);
375 PetscOffloadMask mask;
376 if (dv && hv) { mask = PETSC_OFFLOAD_BOTH; }
377 else if (dv) { mask = PETSC_OFFLOAD_GPU; }
378 else { mask = PETSC_OFFLOAD_CPU; }
379 ierr = __mfem_VecSetOffloadMask(
x,mask); PCHKERRQ(
x,ierr);
386 ierr = VecGetArrayWrite(
x,&v); PCHKERRQ(
x,ierr);
388 ierr = VecRestoreArrayWrite(
x,&v); PCHKERRQ(
x,ierr);
395 MFEM_VERIFY(
x,
"Missing Vec");
396 ierr = VecGetType(
x,&vectype); PCHKERRQ(
x,ierr);
397#if defined(_USE_DEVICE)
402 ierr = VecSetType(
x,PETSC_VECDEVICE); PCHKERRQ(
x,ierr);
405 ierr = VecSetType(
x,VECSTANDARD); PCHKERRQ(
x,ierr);
411 ierr = VecSetType(
x,VECSTANDARD); PCHKERRQ(
x,ierr);
419 MFEM_VERIFY(
x,
"Missing Vec");
420#if defined(PETSC_HAVE_DEVICE)
422 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
423 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
424 ""); PCHKERRQ(
x,ierr);
425 if (on_dev && isdevice)
427 ierr = VecDeviceGetArrayRead(
x,&dummy); PCHKERRQ(
x,ierr);
428 ierr = VecDeviceRestoreArrayRead(
x,&dummy); PCHKERRQ(
x,ierr);
433 ierr = VecGetArrayRead(
x,&dummy); PCHKERRQ(
x,ierr);
434 ierr = VecRestoreArrayRead(
x,&dummy); PCHKERRQ(
x,ierr);
448 MFEM_VERIFY(
x,
"Missing Vec");
449#if defined(PETSC_HAVE_DEVICE)
451 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
452 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
453 ""); PCHKERRQ(
x,ierr);
454 if (on_dev && isdevice)
456 ierr = VecDeviceGetArrayWrite(
x,&dummy); PCHKERRQ(
x,ierr);
457 ierr = VecDeviceRestoreArrayWrite(
x,&dummy); PCHKERRQ(
x,ierr);
462 ierr = VecGetArrayWrite(
x,&dummy); PCHKERRQ(
x,ierr);
463 ierr = VecRestoreArrayWrite(
x,&dummy); PCHKERRQ(
x,ierr);
465 ierr = __mfem_PetscObjectStateIncrease((
PetscObject)
x); PCHKERRQ(
x,ierr);
478 MFEM_VERIFY(
x,
"Missing Vec");
479#if defined(PETSC_HAVE_DEVICE)
481 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
482 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
483 ""); PCHKERRQ(
x,ierr);
484 if (on_dev && isdevice)
486 ierr = VecDeviceGetArray(
x,&dummy); PCHKERRQ(
x,ierr);
487 ierr = VecDeviceRestoreArray(
x,&dummy); PCHKERRQ(
x,ierr);
492 ierr = VecGetArray(
x,&dummy); PCHKERRQ(
x,ierr);
493 ierr = VecRestoreArray(
x,&dummy); PCHKERRQ(
x,ierr);
495 ierr = __mfem_PetscObjectStateIncrease((
PetscObject)
x); PCHKERRQ(
x,ierr);
507 MFEM_VERIFY(
x,
"Missing Vec");
508#if defined(PETSC_HAVE_DEVICE)
509 ierr = VecBindToCPU(
x,!dev ? PETSC_TRUE : PETSC_FALSE); PCHKERRQ(
x,ierr);
517 MFEM_VERIFY(
x,
"Missing Vec");
518 ierr = __mfem_VecBoundToCPU(
x,&flg); PCHKERRQ(
x,ierr);
519 return flg ? false :
true;
525 ierr = VecGetSize(
x,&N); PCHKERRQ(
x,ierr);
531 ierr = VecSetBlockSize(
x,bs); PCHKERRQ(
x,ierr);
540 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
541 ierr = VecSetSizes(
x,n,PETSC_DECIDE); PCHKERRQ(
x,ierr);
544 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
545 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
546 ""); PCHKERRQ(
x,ierr);
552#if defined(PETSC_HAVE_DEVICE)
556 ierr = VecDeviceGetArrayWrite(
x,&array); PCHKERRQ(
x,ierr);
557 rest = VecDeviceRestoreArrayWrite;
563 ierr = VecGetArrayWrite(
x,&array); PCHKERRQ(
x,ierr);
564 rest = VecRestoreArrayWrite;
567 ierr = (*rest)(
x,&array); PCHKERRQ(
x,ierr);
586 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
590 mpiierr = MPI_Comm_rank(comm, &myid); CCHKERRQ(comm, mpiierr);
591 ierr = VecSetSizes(
x,col[myid+1]-col[myid],PETSC_DECIDE); PCHKERRQ(
x,ierr);
595 ierr = VecSetSizes(
x,PETSC_DECIDE,glob_size); PCHKERRQ(
x,ierr);
604 ierr = VecDestroy(&
x); CCHKERRQ(comm,ierr);
611 MFEM_VERIFY(col,
"Missing distribution");
613 mpiierr = MPI_Comm_rank(comm, &myid); CCHKERRQ(comm, mpiierr);
614 ierr = VecCreateMPIWithArray(comm,1,col[myid+1]-col[myid],glob_size,data_,
615 &
x); CCHKERRQ(comm,ierr)
622 ierr = VecDuplicate(y.
x,&
x); PCHKERRQ(
x,ierr);
627 bool transpose,
bool allocate) :
Vector()
631 ierr = VecCreate(comm,&
x);
633 ierr = VecSetSizes(
x,loc,PETSC_DECIDE);
648 bool transpose,
bool allocate) :
Vector()
653 ierr = MatCreateVecs(pA,&
x,NULL); PCHKERRQ(pA,ierr);
657 ierr = MatCreateVecs(pA,NULL,&
x); PCHKERRQ(pA,ierr);
663 ierr = VecGetLocalSize(
x,&n); PCHKERRQ(
x,ierr);
676 ierr = PetscObjectReference((
PetscObject)y); PCHKERRQ(y,ierr);
685 MPI_Comm comm = pfes->
GetComm();
686 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
688 PetscMPIInt myid = 0;
689 if (!HYPRE_AssumedPartitionCheck())
691 mpiierr = MPI_Comm_rank(comm, &myid); CCHKERRQ(comm, mpiierr);
693 ierr = VecSetSizes(
x,offsets[myid+1]-offsets[myid],PETSC_DECIDE);
711 ierr = VecScatterCreateToAll(
x,&scctx,&vout); PCHKERRQ(
x,ierr);
712 ierr = VecScatterBegin(scctx,
x,vout,INSERT_VALUES,SCATTER_FORWARD);
714 ierr = VecScatterEnd(scctx,
x,vout,INSERT_VALUES,SCATTER_FORWARD);
716 ierr = VecScatterDestroy(&scctx); PCHKERRQ(
x,ierr);
717 ierr = VecGetArrayRead(vout,&array); PCHKERRQ(
x,ierr);
718 ierr = VecGetLocalSize(vout,&
size); PCHKERRQ(
x,ierr);
721 ierr = VecRestoreArrayRead(vout,&array); PCHKERRQ(
x,ierr);
722 ierr = VecDestroy(&vout); PCHKERRQ(
x,ierr);
731 ierr = VecSet(
x,d); PCHKERRQ(
x,ierr);
739 MFEM_VERIFY(idx.
Size() == vals.
Size(),
740 "Size mismatch between indices and values");
744 ierr = VecAssemblyBegin(
x); PCHKERRQ(
x,ierr);
745 ierr = VecAssemblyEnd(
x); PCHKERRQ(
x,ierr);
753 MFEM_VERIFY(idx.
Size() == vals.
Size(),
754 "Size mismatch between indices and values");
758 ierr = VecAssemblyBegin(
x); PCHKERRQ(
x,ierr);
759 ierr = VecAssemblyEnd(
x); PCHKERRQ(
x,ierr);
766 ierr = VecCopy(y.
x,
x); PCHKERRQ(
x,ierr);
773 ierr = VecAXPY(
x,1.0,y.
x); PCHKERRQ(
x,ierr);
780 ierr = VecAXPY(
x,-1.0,y.
x); PCHKERRQ(
x,ierr);
787 ierr = VecScale(
x,s); PCHKERRQ(
x,ierr);
794 ierr = VecShift(
x,s); PCHKERRQ(
x,ierr);
801 ierr = VecPlaceArray(
x,temp_data); PCHKERRQ(
x,ierr);
806 ierr = VecResetArray(
x); PCHKERRQ(
x,ierr);
813 ierr = VecGetLocalSize(
x,&n); PCHKERRQ(
x,ierr);
815 "Memory size " << mem.
Capacity() <<
" < " << n <<
" vector size!");
816 MFEM_VERIFY(
pdata.
Empty(),
"Vector data is not empty");
817 MFEM_VERIFY(
data.
Empty(),
"Vector data is not empty");
818#if defined(_USE_DEVICE)
820 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
821 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
822 ""); PCHKERRQ(
x,ierr);
829 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_GPU); PCHKERRQ(
x,ierr);
834 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_CPU); PCHKERRQ(
x,ierr);
844#if defined(PETSC_HAVE_DEVICE)
845 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_CPU); PCHKERRQ(
x,ierr);
847 ierr = VecPlaceArray(
x,w); PCHKERRQ(
x,ierr);
849 ierr = __mfem_PetscObjectStateIncrease((
PetscObject)
x); PCHKERRQ(
x,ierr);
857 ierr = VecGetLocalSize(
x,&n); PCHKERRQ(
x,ierr);
859 "Memory size " << mem.
Capacity() <<
" < " << n <<
" vector size!");
860 MFEM_VERIFY(
pdata.
Empty(),
"Vector data is not empty");
861 MFEM_VERIFY(
data.
Empty(),
"Vector data is not empty");
862#if defined(_USE_DEVICE)
864 ierr = PetscObjectTypeCompareAny((
PetscObject)
x,&isdevice,
865 VECSEQCUDA,VECMPICUDA,VECSEQHIP,VECMPIHIP,
866 ""); PCHKERRQ(
x,ierr);
872 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_GPU); PCHKERRQ(
x,ierr);
877 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_CPU); PCHKERRQ(
x,ierr);
886#if defined(PETSC_HAVE_DEVICE)
887 ierr = __mfem_VecSetOffloadMask(
x,PETSC_OFFLOAD_CPU); PCHKERRQ(
x,ierr);
889 ierr = VecPlaceArray(
x,w); PCHKERRQ(
x,ierr);
892 ierr = __mfem_PetscObjectStateIncrease((
PetscObject)
x); PCHKERRQ(
x,ierr);
893 ierr = VecLockReadPush(
x); PCHKERRQ(
x,ierr);
899 MFEM_VERIFY(!
pdata.
Empty(),
"Vector data is empty");
911#if defined(PETSC_HAVE_DEVICE)
912 PetscOffloadMask mask;
913 ierr = VecGetOffloadMask(
x,&mask); PCHKERRQ(
x,ierr);
914 if ((usedev && (mask != PETSC_OFFLOAD_GPU && mask != PETSC_OFFLOAD_BOTH)) ||
915 (!usedev && (mask != PETSC_OFFLOAD_CPU && mask != PETSC_OFFLOAD_BOTH)))
918 ierr = VecGetArrayRead(
x,&v); PCHKERRQ(
x,ierr);
920 ierr = VecRestoreArrayRead(
x,&v); PCHKERRQ(
x,ierr);
925 if (
read && !
write) { ierr = VecLockReadPop(
x); PCHKERRQ(
x,ierr); }
928#if defined(PETSC_HAVE_DEVICE)
929 ierr = VecDeviceResetArray(
x); PCHKERRQ(
x,ierr);
931 MFEM_VERIFY(
false,
"This should not happen");
936 ierr = VecResetArray(
x); PCHKERRQ(
x,ierr);
942 PetscRandom rctx = NULL;
946 ierr = PetscRandomCreate(PetscObjectComm((
PetscObject)
x),&rctx);
948 ierr = PetscRandomSetSeed(rctx,(
unsigned long)seed); PCHKERRQ(
x,ierr);
949 ierr = PetscRandomSeed(rctx); PCHKERRQ(
x,ierr);
951 ierr = VecSetRandom(
x,rctx); PCHKERRQ(
x,ierr);
952 ierr = PetscRandomDestroy(&rctx); PCHKERRQ(
x,ierr);
963 ierr = PetscViewerBinaryOpen(PetscObjectComm((
PetscObject)
x),fname,
964 FILE_MODE_WRITE,&view);
968 ierr = PetscViewerASCIIOpen(PetscObjectComm((
PetscObject)
x),fname,&view);
971 ierr = VecView(
x,view); PCHKERRQ(
x,ierr);
972 ierr = PetscViewerDestroy(&view); PCHKERRQ(
x,ierr);
976 ierr = VecView(
x,NULL); PCHKERRQ(
x,ierr);
985 ierr = MatGetOwnershipRange(
A,&
N,NULL); PCHKERRQ(
A,ierr);
992 ierr = MatGetOwnershipRangeColumn(
A,&
N,NULL); PCHKERRQ(
A,ierr);
999 ierr = MatGetLocalSize(
A,&
N,NULL); PCHKERRQ(
A,ierr);
1006 ierr = MatGetLocalSize(
A,NULL,&
N); PCHKERRQ(
A,ierr);
1013 ierr = MatGetSize(
A,&
N,NULL); PCHKERRQ(
A,ierr);
1020 ierr = MatGetSize(
A,NULL,&
N); PCHKERRQ(
A,ierr);
1027 ierr = MatGetInfo(
A,MAT_GLOBAL_SUM,&info); PCHKERRQ(
A,ierr);
1033 if (cbs < 0) { cbs = rbs; }
1034 ierr = MatSetBlockSizes(
A,rbs,cbs); PCHKERRQ(
A,ierr);
1058 rows.
GetData(),PETSC_USE_POINTER,&isr); PCHKERRQ(B,ierr);
1060 cols.
GetData(),PETSC_USE_POINTER,&isc); PCHKERRQ(B,ierr);
1061 ierr = MatCreateSubMatrix(B,isr,isc,MAT_INITIAL_MATRIX,&
A); PCHKERRQ(B,ierr);
1062 ierr = ISDestroy(&isr); PCHKERRQ(B,ierr);
1063 ierr = ISDestroy(&isc); PCHKERRQ(B,ierr);
1107 BlockDiagonalConstructor(comm,row_starts,row_starts,diag,
1121 BlockDiagonalConstructor(comm,row_starts,col_starts,diag,
1134 ierr = MatDestroy(&
A); CCHKERRQ(comm,ierr);
1135 if (
X) {
delete X; }
1136 if (
Y) {
delete Y; }
1141#if defined(PETSC_HAVE_HYPRE)
1142 ierr = MatCreateFromParCSR(B,MATAIJ,PETSC_USE_POINTER,&
A);
1144 ierr = MatConvert_hypreParCSR_AIJ(B,&
A); CCHKERRQ(B.
GetComm(),ierr);
1155 ierr = MatDestroy(&
A); CCHKERRQ(comm,ierr);
1156 if (
X) {
delete X; }
1157 if (
Y) {
delete Y; }
1162 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
1170 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
1174 MFEM_VERIFY(
height == B.
Height(),
"Invalid number of local rows");
1175 MFEM_VERIFY(
width == B.
Width(),
"Invalid number of local columns");
1176 ierr = MatAXPY(
A,1.0,B,DIFFERENT_NONZERO_PATTERN); CCHKERRQ(B.
GetComm(),ierr);
1185 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
1186 ierr = MatScale(
A,-1.0); PCHKERRQ(
A,ierr);
1190 MFEM_VERIFY(
height == B.
Height(),
"Invalid number of local rows");
1191 MFEM_VERIFY(
width == B.
Width(),
"Invalid number of local columns");
1192 ierr = MatAXPY(
A,-1.0,B,DIFFERENT_NONZERO_PATTERN); CCHKERRQ(B.
GetComm(),ierr);
1197void PetscParMatrix::
1198BlockDiagonalConstructor(MPI_Comm comm,
1203 PetscInt lrsize,lcsize,rstart,cstart;
1204 PetscMPIInt myid = 0,commsize;
1206 mpiierr = MPI_Comm_size(comm,&commsize); CCHKERRQ(comm,mpiierr);
1207 if (!HYPRE_AssumedPartitionCheck())
1209 mpiierr = MPI_Comm_rank(comm,&myid); CCHKERRQ(comm,mpiierr);
1211 lrsize = row_starts[myid+1]-row_starts[myid];
1212 rstart = row_starts[myid];
1213 lcsize = col_starts[myid+1]-col_starts[myid];
1214 cstart = col_starts[myid];
1219 ierr = ISCreateStride(comm,diag->
Height(),rstart,1,&is); CCHKERRQ(comm,ierr);
1220 ISLocalToGlobalMapping rl2g,cl2g;
1221 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g); PCHKERRQ(is,ierr);
1222 ierr = ISDestroy(&is); CCHKERRQ(comm,ierr);
1223 if (row_starts != col_starts)
1225 ierr = ISCreateStride(comm,diag->
Width(),cstart,1,&is);
1226 CCHKERRQ(comm,ierr);
1227 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g); PCHKERRQ(is,ierr);
1228 ierr = ISDestroy(&is); CCHKERRQ(comm,ierr);
1232 ierr = PetscObjectReference((
PetscObject)rl2g); PCHKERRQ(rl2g,ierr);
1237 ierr = MatCreate(comm,&
A); CCHKERRQ(comm,ierr);
1238 ierr = MatSetSizes(
A,lrsize,lcsize,PETSC_DECIDE,PETSC_DECIDE);
1240 ierr = MatSetType(
A,MATIS); PCHKERRQ(
A,ierr);
1241 ierr = MatSetLocalToGlobalMapping(
A,rl2g,cl2g); PCHKERRQ(
A,ierr);
1242 ierr = ISLocalToGlobalMappingDestroy(&rl2g); PCHKERRQ(
A,ierr)
1243 ierr = ISLocalToGlobalMappingDestroy(&cl2g); PCHKERRQ(
A,ierr)
1248 ierr = MatISGetLocalMat(
A,&lA); PCHKERRQ(
A,ierr);
1251#if defined(PETSC_USE_64BIT_INDICES)
1254 ierr = PetscMalloc2(m,&pII,nnz,&pJJ); PCHKERRQ(lA,ierr);
1255 for (
int i = 0; i < m; i++) { pII[i] = II[i]; }
1256 for (
int i = 0; i < nnz; i++) { pJJ[i] = JJ[i]; }
1257 ierr = MatSeqAIJSetPreallocationCSR(lA,pII,pJJ,
1259 ierr = PetscFree2(pII,pJJ); PCHKERRQ(lA,ierr);
1261 ierr = MatSeqAIJSetPreallocationCSR(lA,II,JJ,
1274 ierr = PetscMalloc1(m,&dii); CCHKERRQ(PETSC_COMM_SELF,ierr);
1275 ierr = PetscMalloc1(nnz,&djj); CCHKERRQ(PETSC_COMM_SELF,ierr);
1276 ierr = PetscMalloc1(nnz,&da); CCHKERRQ(PETSC_COMM_SELF,ierr);
1277 if (
sizeof(
PetscInt) ==
sizeof(
int))
1280 CCHKERRQ(PETSC_COMM_SELF,ierr);
1282 CCHKERRQ(PETSC_COMM_SELF,ierr);
1288 for (
int i = 0; i < m; i++) { dii[i] = iii[i]; }
1289 for (
int i = 0; i < nnz; i++) { djj[i] = jjj[i]; }
1292 CCHKERRQ(PETSC_COMM_SELF,ierr);
1293 ierr = PetscCalloc1(m,&oii);
1294 CCHKERRQ(PETSC_COMM_SELF,ierr);
1297 ierr = MatCreateMPIAIJWithSplitArrays(comm,lrsize,lcsize,PETSC_DECIDE,
1299 dii,djj,da,oii,NULL,NULL,&
A);
1300 CCHKERRQ(comm,ierr);
1304 ierr = MatCreateSeqAIJWithArrays(comm,lrsize,lcsize,dii,djj,da,&
A);
1305 CCHKERRQ(comm,ierr);
1308 void *ptrs[4] = {dii,djj,da,oii};
1309 const char *names[4] = {
"_mfem_csr_dii",
1318 ierr = PetscContainerCreate(comm,&c); CCHKERRQ(comm,ierr);
1319 ierr = PetscContainerSetPointer(c,ptrs[i]); CCHKERRQ(comm,ierr);
1320#if PETSC_VERSION_LT(3,23,0)
1321 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
1323 ierr = PetscContainerSetCtxDestroy(c,__mfem_array_container_destroy);
1325 CCHKERRQ(comm,ierr);
1327 CCHKERRQ(comm,ierr);
1328 ierr = PetscContainerDestroy(&c); CCHKERRQ(comm,ierr);
1333 ierr = MatAssemblyBegin(
A,MAT_FINAL_ASSEMBLY); PCHKERRQ(
A,ierr);
1334 ierr = MatAssemblyEnd(
A,MAT_FINAL_ASSEMBLY); PCHKERRQ(
A,ierr);
1354 ierr = MatCreate(comm,
A); CCHKERRQ(comm,ierr);
1356 PETSC_DECIDE,PETSC_DECIDE); PCHKERRQ(
A,ierr);
1357 ierr = MatSetType(*
A,MATSHELL); PCHKERRQ(
A,ierr);
1358 ierr = MatShellSetContext(*
A,(
void *)op); PCHKERRQ(
A,ierr);
1359#if PETSC_VERSION_LT(3,24,0)
1360 ierr = MatShellSetOperation(*
A,MATOP_MULT,
1361 (
void (*)())__mfem_mat_shell_apply);
1363 ierr = MatShellSetOperation(*
A,MATOP_MULT_TRANSPOSE,
1364 (
void (*)())__mfem_mat_shell_apply_transpose);
1366 ierr = MatShellSetOperation(*
A,MATOP_COPY,
1367 (
void (*)())__mfem_mat_shell_copy);
1369 ierr = MatShellSetOperation(*
A,MATOP_DESTROY,
1370 (
void (*)())__mfem_mat_shell_destroy);
1372 ierr = MatShellSetOperation(*
A,MATOP_MULT,
1373 (PetscErrorCodeFn*)__mfem_mat_shell_apply);
1375 ierr = MatShellSetOperation(*
A,MATOP_MULT_TRANSPOSE,
1376 (PetscErrorCodeFn*)__mfem_mat_shell_apply_transpose);
1378 ierr = MatShellSetOperation(*
A,MATOP_COPY,
1379 (PetscErrorCodeFn*)__mfem_mat_shell_copy);
1381 ierr = MatShellSetOperation(*
A,MATOP_DESTROY,
1382 (PetscErrorCodeFn*)__mfem_mat_shell_destroy);
1384#if defined(_USE_DEVICE)
1388 ierr = MatShellSetVecType(*
A,PETSC_VECDEVICE); PCHKERRQ(
A,ierr);
1389 ierr = MatBindToCPU(*
A,PETSC_FALSE); PCHKERRQ(
A,ierr);
1393 ierr = MatBindToCPU(*
A,PETSC_TRUE); PCHKERRQ(
A,ierr);
1397 ierr = MatSetUp(*
A); PCHKERRQ(*
A,ierr);
1422 PetscBool avoidmatconvert = PETSC_FALSE;
1425 ierr = PetscObjectTypeCompareAny((
PetscObject)(pA->
A),&avoidmatconvert,MATMFFD,
1427 CCHKERRQ(comm,ierr);
1429 if (pA && !avoidmatconvert)
1433#if PETSC_VERSION_LT(3,10,0)
1437#if PETSC_VERSION_LT(3,18,0)
1438 ierr = PetscObjectTypeCompare((
PetscObject)(pA->
A),MATTRANSPOSEMAT,&istrans);
1440 ierr = PetscObjectTypeCompare((
PetscObject)(pA->
A),MATTRANSPOSEVIRTUAL,
1453#if PETSC_VERSION_LT(3,10,0)
1454 ierr = PetscObjectTypeCompare((
PetscObject)(pA->
A),MATIS,&ismatis);
1460 ierr = MatTransposeGetMat(pA->
A,&At); CCHKERRQ(pA->
GetComm(),ierr);
1461#if PETSC_VERSION_LT(3,10,0)
1462 ierr = PetscObjectTypeCompare((
PetscObject)(At),MATIS,&ismatis);
1470#if PETSC_VERSION_LT(3,10,0)
1477 ierr = MatISGetMPIXAIJ(At,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
1478 ierr = MatCreateTranspose(B,
A); PCHKERRQ(pA->
A,ierr);
1479 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
1483 ierr = MatISGetMPIXAIJ(pA->
A,MAT_INITIAL_MATRIX,
A);
1484 PCHKERRQ(pA->
A,ierr);
1491 mpiierr = MPI_Comm_size(comm,&size); CCHKERRQ(comm,mpiierr);
1497 ierr = MatConvert(At,size > 1 ? MATMPIAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);
1498 PCHKERRQ(pA->
A,ierr);
1499 ierr = MatCreateTranspose(B,
A); PCHKERRQ(pA->
A,ierr);
1500 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
1504 ierr = MatConvert(pA->
A, size > 1 ? MATMPIAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,
A);
1505 PCHKERRQ(pA->
A,ierr);
1514 ierr = MatConvert(At,MATIS,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
1515 ierr = MatCreateTranspose(B,
A); PCHKERRQ(pA->
A,ierr);
1516 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
1520 ierr = MatConvert(pA->
A,MATIS,MAT_INITIAL_MATRIX,
A); PCHKERRQ(pA->
A,ierr);
1525#if defined(PETSC_HAVE_HYPRE)
1529 ierr = MatConvert(At,MATHYPRE,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
1530 ierr = MatCreateTranspose(B,
A); PCHKERRQ(pA->
A,ierr);
1531 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
1535 ierr = MatConvert(pA->
A,MATHYPRE,MAT_INITIAL_MATRIX,
A); PCHKERRQ(pA->
A,ierr);
1538 MFEM_ABORT(
"Reconfigure PETSc with --download-hypre or --with-hypre")
1547 MFEM_ABORT(
"Unsupported operator type conversion " << tid)
1554#if defined(PETSC_HAVE_HYPRE)
1555 ierr = MatCreateFromParCSR(
const_cast<HypreParMatrix&
>(*pH),MATAIJ,
1556 PETSC_USE_POINTER,
A);
1558 ierr = MatConvert_hypreParCSR_AIJ(
const_cast<HypreParMatrix&
>(*pH),
A);
1564#if defined(PETSC_HAVE_HYPRE)
1565 ierr = MatCreateFromParCSR(
const_cast<HypreParMatrix&
>(*pH),MATIS,
1566 PETSC_USE_POINTER,
A);
1574#if defined(PETSC_HAVE_HYPRE)
1575 ierr = MatCreateFromParCSR(
const_cast<HypreParMatrix&
>(*pH),MATHYPRE,
1576 PETSC_USE_POINTER,
A);
1579 MFEM_ABORT(
"Reconfigure PETSc with --download-hypre or --with-hypre")
1588 MFEM_ABORT(
"Conversion from HypreParCSR to operator type = " << tid <<
1589 " is not implemented");
1594 Mat *mats,*matsl2l = NULL;
1599 ierr = PetscCalloc1(nr*nc,&mats); CCHKERRQ(PETSC_COMM_SELF,ierr);
1602 ierr = PetscCalloc1(nr,&matsl2l); CCHKERRQ(PETSC_COMM_SELF,ierr);
1604 for (i=0; i<nr; i++)
1606 PetscBool needl2l = PETSC_TRUE;
1608 for (j=0; j<nc; j++)
1616 ierr = PetscObjectQuery((
PetscObject)mats[i*nc+j],
"_MatIS_PtAP_l2l",
1618 PCHKERRQ(mats[i*nc+j],ierr);
1626 ierr = PetscContainerGetPointer(c,(
void**)&l2l);
1628 MFEM_VERIFY(l2l->
Size() == 1,
"Unexpected size "
1629 << l2l->
Size() <<
" for block row " << i );
1630 ierr = PetscObjectReference((
PetscObject)(*l2l)[0]);
1632 matsl2l[i] = (*l2l)[0];
1633 needl2l = PETSC_FALSE;
1639 ierr = MatCreateNest(comm,nr,NULL,nc,NULL,mats,
A); CCHKERRQ(comm,ierr);
1642 ierr = MatConvert(*
A,MATIS,MAT_INPLACE_MATRIX,
A); CCHKERRQ(comm,ierr);
1645 for (
int i=0; i<(int)nr; i++) { (*vmatsl2l)[i] = matsl2l[i]; }
1646 ierr = PetscFree(matsl2l); CCHKERRQ(PETSC_COMM_SELF,ierr);
1649 ierr = PetscContainerCreate(comm,&c); CCHKERRQ(comm,ierr);
1650 ierr = PetscContainerSetPointer(c,vmatsl2l); PCHKERRQ(c,ierr);
1651#if PETSC_VERSION_LT(3,23,0)
1652 ierr = PetscContainerSetUserDestroy(c,__mfem_matarray_container_destroy);
1654 ierr = PetscContainerSetCtxDestroy(c,__mfem_matarray_container_destroy);
1658 PCHKERRQ((*
A),ierr);
1659 ierr = PetscContainerDestroy(&c); CCHKERRQ(comm,ierr);
1661 for (i=0; i<nr*nc; i++) { ierr = MatDestroy(&mats[i]); CCHKERRQ(comm,ierr); }
1662 ierr = PetscFree(mats); CCHKERRQ(PETSC_COMM_SELF,ierr);
1668 ierr = MatCreate(comm,
A); CCHKERRQ(comm,ierr);
1669 ierr = MatSetSizes(*
A,pI->
Height(),pI->
Width(),PETSC_DECIDE,PETSC_DECIDE);
1671 ierr = MatSetType(*
A,MATAIJ); PCHKERRQ(*
A,ierr);
1672 ierr = MatMPIAIJSetPreallocation(*
A,1,NULL,0,NULL); PCHKERRQ(*
A,ierr);
1673 ierr = MatSeqAIJSetPreallocation(*
A,1,NULL); PCHKERRQ(*
A,ierr);
1674 ierr = MatSetOption(*
A,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE); PCHKERRQ(*
A,ierr);
1675 ierr = MatGetOwnershipRange(*
A,&rst,NULL); PCHKERRQ(*
A,ierr);
1678 ierr = MatSetValue(*
A,i,i,1.,INSERT_VALUES); PCHKERRQ(*
A,ierr);
1680 ierr = MatAssemblyBegin(*
A,MAT_FINAL_ASSEMBLY); PCHKERRQ(*
A,ierr);
1681 ierr = MatAssemblyEnd(*
A,MAT_FINAL_ASSEMBLY); PCHKERRQ(*
A,ierr);
1698 int n = pS->
Width();
1703 ierr = PetscMalloc1(m+1,&pii); CCHKERRQ(PETSC_COMM_SELF,ierr);
1704 ierr = PetscMalloc1(ii[m],&pjj); CCHKERRQ(PETSC_COMM_SELF,ierr);
1705 ierr = PetscMalloc1(ii[m],&pdata); CCHKERRQ(PETSC_COMM_SELF,ierr);
1707 for (
int i = 0; i < m; i++)
1709 bool issorted =
true;
1711 for (
int j = ii[i]; j < ii[i+1]; j++)
1714 if (issorted && j != ii[i]) { issorted = (pjj[j] > pjj[j-1]); }
1719 ierr = PetscSortIntWithScalarArray(pii[i+1]-pii[i],pjj + pii[i],pdata + pii[i]);
1720 CCHKERRQ(PETSC_COMM_SELF,ierr);
1724 mpiierr = MPI_Comm_size(comm,&size); CCHKERRQ(comm,mpiierr);
1727 ierr = MatCreateSeqAIJWithArrays(comm,m,n,pii,pjj,pdata,&B);
1728 CCHKERRQ(comm,ierr);
1733 ierr = PetscCalloc1(m+1,&oii); CCHKERRQ(PETSC_COMM_SELF,ierr);
1734 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,
1736 pii,pjj,pdata,oii,NULL,NULL,&B);
1737 CCHKERRQ(comm,ierr);
1739 void *ptrs[4] = {pii,pjj,pdata,oii};
1740 const char *names[4] = {
"_mfem_csr_pii",
1745 for (
int i=0; i<4; i++)
1749 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c); PCHKERRQ(B,ierr);
1750 ierr = PetscContainerSetPointer(c,ptrs[i]); PCHKERRQ(B,ierr);
1751#if PETSC_VERSION_LT(3,23,0)
1752 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
1754 ierr = PetscContainerSetCtxDestroy(c,__mfem_array_container_destroy);
1759 ierr = PetscContainerDestroy(&c); PCHKERRQ(B,ierr);
1767 ierr = MatConvert(B,MATHYPRE,MAT_INITIAL_MATRIX,
A); PCHKERRQ(B,ierr);
1768 ierr = MatDestroy(&B); PCHKERRQ(*
A,ierr);
1772 ierr = MatConvert(B,MATIS,MAT_INITIAL_MATRIX,
A); PCHKERRQ(B,ierr);
1773 ierr = MatDestroy(&B); PCHKERRQ(*
A,ierr);
1777 MFEM_ABORT(
"Unsupported operator type conversion " << tid)
1784 "Supported types are ANY_TYPE, PETSC_MATSHELL or PETSC_MATAIJ");
1791 ierr = MatComputeOperator(*
A,MATMPIAIJ,&B); CCHKERRQ(comm,ierr);
1792 ierr = PetscObjectTypeCompare((
PetscObject)B,MATMPIAIJ,&isaij);
1793 CCHKERRQ(comm,ierr);
1794 ierr = MatDestroy(
A); CCHKERRQ(comm,ierr);
1797 ierr = MatConvert(B,MATAIJ,MAT_INITIAL_MATRIX,
A); CCHKERRQ(comm,ierr);
1798 ierr = MatDestroy(&B); CCHKERRQ(comm,ierr);
1813 MPI_Comm comm = MPI_COMM_NULL;
1814 ierr = PetscObjectGetComm((
PetscObject)
A,&comm); PCHKERRQ(
A,ierr);
1815 ierr = MatDestroy(&
A); CCHKERRQ(comm,ierr);
1826 ierr = PetscObjectReference((
PetscObject)
a); PCHKERRQ(
a,ierr);
1836 if (A_ ==
A) {
return; }
1838 ierr = PetscObjectReference((
PetscObject)A_); PCHKERRQ(A_,ierr);
1844void PetscParMatrix::SetUpForDevice()
1846#if !defined(_USE_DEVICE)
1852 if (
A) { ierr = MatBindToCPU(
A, PETSC_TRUE); PCHKERRQ(
A,ierr); }
1855 PetscBool ismatis,isnest,isaij;
1856 ierr = PetscObjectTypeCompare((
PetscObject)
A,MATIS,&ismatis);
1858 ierr = PetscObjectTypeCompare((
PetscObject)
A,MATNEST,&isnest);
1863 ierr = MatISGetLocalMat(
A,&tA); PCHKERRQ(
A,ierr);
1864 ierr = PetscObjectTypeCompare((
PetscObject)tA,MATNEST,&isnest);
1871 ierr = MatNestGetSubMats(tA,&n,&m,&sub); PCHKERRQ(tA,ierr);
1881 ierr = PetscObjectTypeCompareAny((
PetscObject)sA,&isaij,MATSEQAIJ,MATMPIAIJ,
"");
1885 ierr = MatSetType(sA,PETSC_MATAIJDEVICE); PCHKERRQ(sA,ierr);
1891 ierr = MatSetOption(sA,MAT_FORM_EXPLICIT_TRANSPOSE,
1892 PETSC_TRUE); PCHKERRQ(sA,ierr);
1899 ierr = MatSetVecType(tA,PETSC_VECDEVICE); PCHKERRQ(tA,ierr);
1905 ierr = PetscObjectTypeCompareAny((
PetscObject)tA,&isaij,MATSEQAIJ,MATMPIAIJ,
"");
1909 ierr = MatSetType(tA,PETSC_MATAIJDEVICE); PCHKERRQ(tA,ierr);
1914 ierr = MatSetOption(tA,MAT_FORM_EXPLICIT_TRANSPOSE,
1915 PETSC_TRUE); PCHKERRQ(tA,ierr);
1930 f = MatMultTranspose;
1931 fadd = MatMultTransposeAdd;
1942 ierr = VecScale(Y,
b/
a); PCHKERRQ(A,ierr);
1943 ierr = (*fadd)(A,X,Y,Y); PCHKERRQ(A,ierr);
1944 ierr = VecScale(Y,
a); PCHKERRQ(A,ierr);
1948 ierr = (*f)(A,X,Y); PCHKERRQ(A,ierr);
1949 ierr = VecScale(Y,
a); PCHKERRQ(A,ierr);
1960 ierr = VecScale(Y,
b); PCHKERRQ(A,ierr);
1964 ierr = VecSet(Y,0.); PCHKERRQ(A,ierr);
1971 ierr = PetscObjectReference((
PetscObject)master.
A); PCHKERRQ(master.
A,ierr);
1983 MFEM_VERIFY(
A,
"Mat not present");
1993 MFEM_VERIFY(
A,
"Mat not present");
2004 ierr = MatCreateTranspose(
A,&B); PCHKERRQ(
A,ierr);
2008 ierr = MatTranspose(
A,MAT_INITIAL_MATRIX,&B); PCHKERRQ(
A,ierr);
2015 ierr = MatScale(
A,s); PCHKERRQ(
A,ierr);
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());
2028 bool rw = (
b != 0.0);
2031 MatMultKernel(
A,
a,XX->
x,
b,YY->
x,
false);
2040 MFEM_ASSERT(x.
Size() ==
Height(),
"invalid x.Size() = " << x.
Size()
2041 <<
", expected size = " <<
Height());
2042 MFEM_ASSERT(y.
Size() ==
Width(),
"invalid y.Size() = " << y.
Size()
2043 <<
", expected size = " <<
Width());
2047 bool rw = (
b != 0.0);
2050 MatMultKernel(
A,
a,YY->
x,
b,XX->
x,
true);
2063 ierr = PetscViewerBinaryOpen(PetscObjectComm((
PetscObject)
A),fname,
2064 FILE_MODE_WRITE,&view);
2068 ierr = PetscViewerASCIIOpen(PetscObjectComm((
PetscObject)
A),fname,&view);
2071 ierr = MatView(
A,view); PCHKERRQ(
A,ierr);
2072 ierr = PetscViewerDestroy(&view); PCHKERRQ(
A,ierr);
2076 ierr = MatView(
A,NULL); PCHKERRQ(
A,ierr);
2082 MFEM_ASSERT(s.
Size() ==
Height(),
"invalid s.Size() = " << s.
Size()
2083 <<
", expected size = " <<
Height());
2087 ierr = MatDiagonalScale(
A,*YY,NULL); PCHKERRQ(
A,ierr);
2093 MFEM_ASSERT(s.
Size() ==
Width(),
"invalid s.Size() = " << s.
Size()
2094 <<
", expected size = " <<
Width());
2098 ierr = MatDiagonalScale(
A,NULL,*XX); PCHKERRQ(
A,ierr);
2110 MFEM_ASSERT(s.
Size() ==
Height(),
"invalid s.Size() = " << s.
Size()
2111 <<
", expected size = " <<
Height());
2112 MFEM_ASSERT(s.
Size() ==
Width(),
"invalid s.Size() = " << s.
Size()
2113 <<
", expected size = " <<
Width());
2117 ierr = MatDiagonalSet(
A,*XX,ADD_VALUES); PCHKERRQ(
A,ierr);
2125 "Petsc TripleMatrixProduct: Number of local cols of A " << A->
Width() <<
2126 " differs from number of local rows of P " << P->
Height());
2128 "Petsc TripleMatrixProduct: Number of local rows of A " << A->
Height() <<
2129 " differs from number of local cols of R " << R->
Width());
2131 ierr = MatMatMatMult(*R,*A,*P,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
2138 Mat pA = *A,pP = *P,pRt = *Rt;
2140 PetscBool Aismatis,Pismatis,Rtismatis;
2143 "Petsc RAP: Number of local cols of A " << A->
Width() <<
2144 " differs from number of local rows of P " << P->
Height());
2146 "Petsc RAP: Number of local rows of A " << A->
Height() <<
2147 " differs from number of local rows of Rt " << Rt->
Height());
2148 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATIS,&Aismatis);
2150 ierr = PetscObjectTypeCompare((
PetscObject)pP,MATIS,&Pismatis);
2152 ierr = PetscObjectTypeCompare((
PetscObject)pRt,MATIS,&Rtismatis);
2159 ISLocalToGlobalMapping cl2gP,cl2gRt;
2160 PetscInt rlsize,clsize,rsize,csize;
2162 ierr = MatGetLocalToGlobalMapping(pP,NULL,&cl2gP); PCHKERRQ(pA,ierr);
2163 ierr = MatGetLocalToGlobalMapping(pRt,NULL,&cl2gRt); PCHKERRQ(pA,ierr);
2164 ierr = MatGetLocalSize(pP,NULL,&clsize); PCHKERRQ(pP,ierr);
2165 ierr = MatGetLocalSize(pRt,NULL,&rlsize); PCHKERRQ(pRt,ierr);
2166 ierr = MatGetSize(pP,NULL,&csize); PCHKERRQ(pP,ierr);
2167 ierr = MatGetSize(pRt,NULL,&rsize); PCHKERRQ(pRt,ierr);
2168 ierr = MatCreate(A->
GetComm(),&B); PCHKERRQ(pA,ierr);
2169 ierr = MatSetSizes(B,rlsize,clsize,rsize,csize); PCHKERRQ(B,ierr);
2170 ierr = MatSetType(B,MATIS); PCHKERRQ(B,ierr);
2171 ierr = MatSetLocalToGlobalMapping(B,cl2gRt,cl2gP); PCHKERRQ(B,ierr);
2172 ierr = MatISGetLocalMat(pA,&lA); PCHKERRQ(pA,ierr);
2173 ierr = MatISGetLocalMat(pP,&lP); PCHKERRQ(pA,ierr);
2174 ierr = MatISGetLocalMat(pRt,&lRt); PCHKERRQ(pA,ierr);
2177 ierr = MatPtAP(lA,lP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&lB);
2183 ierr = MatTranspose(lRt,MAT_INITIAL_MATRIX,&lR); PCHKERRQ(lRt,ierr);
2184 ierr = MatMatMatMult(lR,lA,lP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&lB);
2186 ierr = MatDestroy(&lR); PCHKERRQ(lRt,ierr);
2194 ierr = PetscObjectReference((
PetscObject)lRt); PCHKERRQ(lRt,ierr);
2195 (*vmatsl2l)[0] = lRt;
2198 ierr = PetscContainerCreate(PetscObjectComm((
PetscObject)B),&c);
2200 ierr = PetscContainerSetPointer(c,vmatsl2l); PCHKERRQ(c,ierr);
2201#if PETSC_VERSION_LT(3,23,0)
2202 ierr = PetscContainerSetUserDestroy(c,__mfem_matarray_container_destroy);
2204 ierr = PetscContainerSetCtxDestroy(c,__mfem_matarray_container_destroy);
2209 ierr = PetscContainerDestroy(&c); PCHKERRQ(B,ierr);
2213 ierr = MatISSetLocalMat(B,lB); PCHKERRQ(lB,ierr);
2214 ierr = MatDestroy(&lB); PCHKERRQ(lA,ierr);
2215 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); PCHKERRQ(B,ierr);
2216 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); PCHKERRQ(B,ierr);
2222 ierr = MatPtAP(pA,pP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
2228 ierr = MatTranspose(pRt,MAT_INITIAL_MATRIX,&pR); PCHKERRQ(Rt,ierr);
2229 ierr = MatMatMatMult(pR,pA,pP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
2231 ierr = MatDestroy(&pR); PCHKERRQ(pRt,ierr);
2246#if defined(PETSC_HAVE_HYPRE)
2261 ierr = MatMatMult(*A,*B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AB);
2271 ierr = MatDuplicate(
A,MAT_COPY_VALUES,&Ae); PCHKERRQ(
A,ierr);
2273 ierr = MatAXPY(Ae,-1.,
A,SAME_NONZERO_PATTERN); PCHKERRQ(
A,ierr);
2282 MFEM_ABORT(
"Missing PetscParMatrix::EliminateRowsCols() with HypreParVectors");
2291 ierr = MatGetSize(
A,&
M,&
N); PCHKERRQ(
A,ierr);
2292 MFEM_VERIFY(
M ==
N,
"Rectangular case unsupported");
2295 ierr = MatSetOption(
A,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE); PCHKERRQ(
A,ierr);
2299 ierr = MatGetOwnershipRange(
A,&rst,NULL); PCHKERRQ(
A,ierr);
2302 ierr = Convert_Array_IS(
GetComm(),
true,&rows_cols,rst,&dir); PCHKERRQ(
A,ierr);
2305 ierr = MatZeroRowsColumnsIS(
A,dir,diag,NULL,NULL); PCHKERRQ(
A,ierr);
2309 ierr = MatZeroRowsColumnsIS(
A,dir,diag,
X,B); PCHKERRQ(
A,ierr);
2311 ierr = ISDestroy(&dir); PCHKERRQ(
A,ierr);
2316 ierr = MatSetOption(
A,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE); PCHKERRQ(
A,ierr);
2320 ierr = MatGetOwnershipRange(
A,&rst,NULL); PCHKERRQ(
A,ierr);
2323 ierr = Convert_Array_IS(
GetComm(),
true,&rows,rst,&dir); PCHKERRQ(
A,ierr);
2324 ierr = MatZeroRowsIS(
A,dir,0.0,NULL,NULL); PCHKERRQ(
A,ierr);
2325 ierr = ISDestroy(&dir); PCHKERRQ(
A,ierr);
2335 ierr = PetscObjectDereference((
PetscObject)
A); CCHKERRQ(comm,ierr);
2344 MFEM_VERIFY(
A,
"no associated PETSc Mat object");
2347 ierr = PetscObjectBaseTypeCompare(oA, MATSEQAIJ, &ok); PCHKERRQ(
A,ierr);
2349 ierr = PetscObjectBaseTypeCompare(oA, MATMPIAIJ, &ok); PCHKERRQ(
A,ierr);
2351 ierr = PetscObjectTypeCompare(oA, MATIS, &ok); PCHKERRQ(
A,ierr);
2353 ierr = PetscObjectTypeCompare(oA, MATSHELL, &ok); PCHKERRQ(
A,ierr);
2355 ierr = PetscObjectTypeCompare(oA, MATNEST, &ok); PCHKERRQ(
A,ierr);
2357#if defined(PETSC_HAVE_HYPRE)
2358 ierr = PetscObjectTypeCompare(oA, MATHYPRE, &ok); PCHKERRQ(
A,ierr);
2372 Ae.
Mult(-1.0, X, 1.0, B);
2375 ierr = MatGetDiagonal(pA,diag); PCHKERRQ(pA,ierr);
2376 ierr = VecGetArrayRead(diag,&array); PCHKERRQ(diag,ierr);
2377 for (
int i = 0; i < ess_dof_list.
Size(); i++)
2379 int r = ess_dof_list[i];
2380 B(r) = array[r] * X(r);
2382 ierr = VecRestoreArrayRead(diag,&array); PCHKERRQ(diag,ierr);
2411 if (
cid == KSP_CLASSID)
2414 ierr = KSPSetTolerances(ksp,tol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
2416 else if (
cid == SNES_CLASSID)
2418 SNES snes = (SNES)
obj;
2419 ierr = SNESSetTolerances(snes,PETSC_DEFAULT,tol,PETSC_DEFAULT,PETSC_DEFAULT,
2422 else if (
cid == TS_CLASSID)
2425 ierr = TSSetTolerances(ts,PETSC_DECIDE,NULL,tol,NULL);
2429 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2436 if (
cid == KSP_CLASSID)
2439 ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,tol,PETSC_DEFAULT,PETSC_DEFAULT);
2441 else if (
cid == SNES_CLASSID)
2443 SNES snes = (SNES)
obj;
2444 ierr = SNESSetTolerances(snes,tol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
2447 else if (
cid == TS_CLASSID)
2450 ierr = TSSetTolerances(ts,tol,NULL,PETSC_DECIDE,NULL);
2454 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2461 if (
cid == KSP_CLASSID)
2464 ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
2467 else if (
cid == SNES_CLASSID)
2469 SNES snes = (SNES)
obj;
2470 ierr = SNESSetTolerances(snes,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
2471 max_iter,PETSC_DEFAULT);
2473 else if (
cid == TS_CLASSID)
2476 ierr = TSSetMaxSteps(ts,max_iter);
2480 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2488 typedef PetscErrorCode (*myPetscFunc)(
void**);
2489 PetscViewerAndFormat *vf = NULL;
2490 PetscViewer viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm(
obj));
2494 ierr = PetscViewerAndFormatCreate(viewer,PETSC_VIEWER_DEFAULT,&vf);
2497 if (
cid == KSP_CLASSID)
2505 ierr = KSPMonitorCancel(ksp); PCHKERRQ(ksp,ierr);
2509#if PETSC_VERSION_LT(3,15,0)
2510 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorDefault,vf,
2512 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorResidual,vf,
2514 (myPetscFunc)PetscViewerAndFormatDestroy);
2519 ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE); PCHKERRQ(ksp,ierr);
2520 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorSingularValue,vf,
2521 (myPetscFunc)PetscViewerAndFormatDestroy);
2525 ierr = PetscViewerAndFormatCreate(viewer,PETSC_VIEWER_DEFAULT,&vf);
2526 PCHKERRQ(viewer,ierr);
2527#if PETSC_VERSION_LT(3,15,0)
2528 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorTrueResidualNorm,vf,
2530 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorTrueResidual,vf,
2532 (myPetscFunc)PetscViewerAndFormatDestroy);
2537 else if (
cid == SNES_CLASSID)
2540 SNES snes = (SNES)
obj;
2543 ierr = SNESMonitorCancel(snes); PCHKERRQ(snes,ierr);
2547 ierr = SNESMonitorSet(snes,(myMonitor)SNESMonitorDefault,vf,
2548 (myPetscFunc)PetscViewerAndFormatDestroy);
2549 PCHKERRQ(snes,ierr);
2552 else if (
cid == TS_CLASSID)
2557 ierr = TSMonitorCancel(ts); PCHKERRQ(ts,ierr);
2562 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2568 return obj ? PetscObjectComm(
obj) : MPI_COMM_NULL;
2573 __mfem_monitor_ctx *monctx;
2574 ierr = PetscNew(&monctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2575 monctx->solver =
this;
2576 monctx->monitor =
ctx;
2577 if (
cid == KSP_CLASSID)
2579 ierr = KSPMonitorSet((KSP)
obj,__mfem_ksp_monitor,monctx,
2580 __mfem_monitor_ctx_destroy);
2583 else if (
cid == SNES_CLASSID)
2585 ierr = SNESMonitorSet((SNES)
obj,__mfem_snes_monitor,monctx,
2586 __mfem_monitor_ctx_destroy);
2589 else if (
cid == TS_CLASSID)
2591 ierr = TSMonitorSet((TS)
obj,__mfem_ts_monitor,monctx,
2592 __mfem_monitor_ctx_destroy);
2597 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2604 if (
cid == SNES_CLASSID)
2606 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)
private_ctx;
2609 else if (
cid == TS_CLASSID)
2611 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
private_ctx;
2616 MFEM_ABORT(
"Handling of essential bc only implemented for nonlinear and time-dependent solvers");
2623 if (
cid == TS_CLASSID)
2628 ierr = TSGetSNES((TS)
obj,&snes); PCHKERRQ(
obj,ierr);
2629 ierr = SNESGetKSP(snes,&ksp); PCHKERRQ(
obj,ierr);
2630 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(
obj,ierr);
2632 else if (
cid == SNES_CLASSID)
2636 ierr = SNESGetKSP((SNES)
obj,&ksp); PCHKERRQ(
obj,ierr);
2637 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(
obj,ierr);
2639 else if (
cid == KSP_CLASSID)
2641 ierr = KSPGetPC((KSP)
obj,&pc); PCHKERRQ(
obj,ierr);
2643 else if (
cid == PC_CLASSID)
2649 MFEM_ABORT(
"No support for PetscPreconditionerFactory for this object");
2653 ierr = MakeShellPCWithFactory(pc,factory); PCHKERRQ(pc,ierr);
2657 ierr = PCSetType(pc, PCNONE); PCHKERRQ(pc,ierr);
2663 if (!customize) {
clcustom =
true; }
2666 if (
cid == PC_CLASSID)
2669 ierr = PCSetFromOptions(pc); PCHKERRQ(pc, ierr);
2671 else if (
cid == KSP_CLASSID)
2674 ierr = KSPSetFromOptions(ksp); PCHKERRQ(ksp, ierr);
2676 else if (
cid == SNES_CLASSID)
2678 SNES snes = (SNES)
obj;
2679 ierr = SNESSetFromOptions(snes); PCHKERRQ(snes, ierr);
2681 else if (
cid == TS_CLASSID)
2684 ierr = TSSetFromOptions(ts); PCHKERRQ(ts, ierr);
2688 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2696 if (
cid == KSP_CLASSID)
2699 KSPConvergedReason reason;
2700 ierr = KSPGetConvergedReason(ksp,&reason);
2702 return reason > 0 ? 1 : 0;
2704 else if (
cid == SNES_CLASSID)
2706 SNES snes = (SNES)
obj;
2707 SNESConvergedReason reason;
2708 ierr = SNESGetConvergedReason(snes,&reason);
2709 PCHKERRQ(snes,ierr);
2710 return reason > 0 ? 1 : 0;
2712 else if (
cid == TS_CLASSID)
2715 TSConvergedReason reason;
2716 ierr = TSGetConvergedReason(ts,&reason);
2718 return reason > 0 ? 1 : 0;
2722 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2729 if (
cid == KSP_CLASSID)
2733 ierr = KSPGetIterationNumber(ksp,&its);
2737 else if (
cid == SNES_CLASSID)
2739 SNES snes = (SNES)
obj;
2741 ierr = SNESGetIterationNumber(snes,&its);
2742 PCHKERRQ(snes,ierr);
2745 else if (
cid == TS_CLASSID)
2749 ierr = TSGetStepNumber(ts,&its);
2755 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2762 if (
cid == KSP_CLASSID)
2766 ierr = KSPGetResidualNorm(ksp,&
norm);
2770 if (
cid == SNES_CLASSID)
2772 SNES snes = (SNES)
obj;
2774 ierr = SNESGetFunctionNorm(snes,&
norm);
2775 PCHKERRQ(snes,ierr);
2780 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2781 return PETSC_MAX_REAL;
2788 if (
cid == SNES_CLASSID)
2790 __mfem_snes_ctx *snes_ctx;
2791 ierr = PetscNew(&snes_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2792 snes_ctx->op = NULL;
2793 snes_ctx->bchandler = NULL;
2794 snes_ctx->work = NULL;
2798 else if (
cid == TS_CLASSID)
2800 __mfem_ts_ctx *ts_ctx;
2801 ierr = PetscNew(&ts_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2803 ts_ctx->bchandler = NULL;
2804 ts_ctx->work = NULL;
2805 ts_ctx->work2 = NULL;
2806 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
2807 ts_ctx->cached_ijacstate = -1;
2808 ts_ctx->cached_rhsjacstate = -1;
2809 ts_ctx->cached_splits_xstate = -1;
2810 ts_ctx->cached_splits_xdotstate = -1;
2821 if (
cid == SNES_CLASSID)
2823 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx *)
private_ctx;
2824 delete snes_ctx->work;
2826 else if (
cid == TS_CLASSID)
2828 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx *)
private_ctx;
2829 delete ts_ctx->work;
2830 delete ts_ctx->work2;
2832 ierr = PetscFree(
private_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2839 : bctype(type_), setup(false), eval_t(0.0),
2840 eval_t_cached(std::numeric_limits<
mfem::
real_t>::min())
2847 ess_tdof_list.
SetSize(list.Size());
2848 ess_tdof_list.
Assign(list);
2854 if (setup) {
return; }
2858 this->
Eval(eval_t,eval_g);
2859 eval_t_cached = eval_t;
2870 (*this).SetUp(x.
Size());
2874 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2876 y[ess_tdof_list[i]] = 0.0;
2881 if (bctype !=
CONSTANT && eval_t != eval_t_cached)
2883 Eval(eval_t,eval_g);
2884 eval_t_cached = eval_t;
2886 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2888 y[ess_tdof_list[i]] = eval_g[ess_tdof_list[i]];
2895 (*this).SetUp(x.
Size());
2898 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2900 x[ess_tdof_list[i]] = 0.0;
2905 if (bctype !=
CONSTANT && eval_t != eval_t_cached)
2907 Eval(eval_t,eval_g);
2908 eval_t_cached = eval_t;
2910 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2912 x[ess_tdof_list[i]] = eval_g[ess_tdof_list[i]];
2919 (*this).SetUp(x.
Size());
2922 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2924 y[ess_tdof_list[i]] = x[ess_tdof_list[i]];
2929 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2931 y[ess_tdof_list[i]] = x[ess_tdof_list[i]] - eval_g[ess_tdof_list[i]];
2938 (*this).SetUp(x.
Size());
2939 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2941 x[ess_tdof_list[i]] = 0.0;
2947 (*this).SetUp(x.
Size());
2949 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2951 y[ess_tdof_list[i]] = 0.0;
2958 bool wrapin,
bool iter_mode)
2962 ierr = KSPCreate(comm,&ksp); CCHKERRQ(comm,ierr);
2964 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
2965 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2966 ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)
iterative_mode);
2967 PCHKERRQ(ksp, ierr);
2971 const std::string &prefix,
bool iter_mode)
2977 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
2978 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2979 ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)
iterative_mode);
2980 PCHKERRQ(ksp, ierr);
2985 const std::string &prefix,
bool iter_mode)
2991 ierr = PetscObjectGetClassId(
obj, &
cid); PCHKERRQ(
obj, ierr);
2992 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2993 ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)
iterative_mode);
2994 PCHKERRQ(ksp, ierr);
3006 bool delete_pA =
false;
3024 MFEM_VERIFY(pA,
"Unsupported operation!");
3032 PetscInt nheight,nwidth,oheight,owidth;
3034 ierr = KSPGetOperators(ksp,&C,NULL); PCHKERRQ(ksp,ierr);
3035 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
3036 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
3037 if (nheight != oheight || nwidth != owidth)
3041 ierr = KSPReset(ksp); PCHKERRQ(ksp,ierr);
3047 ierr = KSPSetOperators(ksp,A,A); PCHKERRQ(ksp,ierr);
3056 if (delete_pA) {
delete pA; }
3071 bool delete_pA =
false;
3089 MFEM_VERIFY(pA,
"Unsupported operation!");
3092 bool delete_ppA =
false;
3095 if (oA == poA && !wrap)
3105 MFEM_VERIFY(ppA,
"Unsupported operation!");
3114 PetscInt nheight,nwidth,oheight,owidth;
3116 ierr = KSPGetOperators(ksp,&C,NULL); PCHKERRQ(ksp,ierr);
3117 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
3118 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
3119 if (nheight != oheight || nwidth != owidth)
3123 ierr = KSPReset(ksp); PCHKERRQ(ksp,ierr);
3130 ierr = KSPSetOperators(ksp,A,P); PCHKERRQ(ksp,ierr);
3139 if (delete_pA) {
delete pA; }
3140 if (delete_ppA) {
delete ppA; }
3150 ierr = KSPGetOperatorsSet(ksp,&amat,NULL); PCHKERRQ(ksp,ierr);
3153 ierr = KSPGetOperators(ksp,&A,NULL); PCHKERRQ(ksp,ierr);
3154 ierr = PetscObjectReference((
PetscObject)A); PCHKERRQ(ksp,ierr);
3159 ierr = KSPSetPC(ksp,*ppc); PCHKERRQ(ksp,ierr);
3168 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(ksp,ierr);
3169 ierr = MakeShellPC(pc,precond,
false); PCHKERRQ(ksp,ierr);
3175 ierr = KSPGetOperators(ksp,NULL,&P); PCHKERRQ(ksp,ierr);
3176 ierr = PetscObjectReference((
PetscObject)P); PCHKERRQ(ksp,ierr);
3177 ierr = KSPSetOperators(ksp,A,P); PCHKERRQ(ksp,ierr);
3178 ierr = MatDestroy(&A); PCHKERRQ(ksp,ierr);
3179 ierr = MatDestroy(&P); PCHKERRQ(ksp,ierr);
3190 ierr = KSPGetOperators(ksp, &pA, NULL); PCHKERRQ(
obj, ierr);
3198 PetscParMatrix A = PetscParMatrix(pA,
true);
3199 X =
new PetscParVector(A,
false,
false);
3207 ierr = KSPGetInitialGuessNonzero(ksp, &flg);
3213 ierr = KSPSolveTranspose(ksp,
B->
x,
X->
x); PCHKERRQ(ksp,ierr);
3217 ierr = KSPSolve(ksp,
B->
x,
X->
x); PCHKERRQ(ksp,ierr);
3225 (*this).MultKernel(
b,x,
false);
3230 (*this).MultKernel(
b,x,
true);
3237 ierr = PetscObjectGetComm((
PetscObject)ksp,&comm); PCHKERRQ(ksp,ierr);
3238 ierr = KSPDestroy(&ksp); CCHKERRQ(comm,ierr);
3248 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
3250 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
3258 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
3260 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
3264 const std::string &prefix,
bool iter_mode)
3268 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
3270 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
3276 const std::string &prefix)
3280 ierr = PCCreate(comm,&pc); CCHKERRQ(comm,ierr);
3282 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
3283 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
3287 const string &prefix)
3293 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
3294 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
3299 const string &prefix)
3303 ierr = PCCreate(comm,&pc); CCHKERRQ(comm,ierr);
3305 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
3306 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
3312 bool delete_pA =
false;
3329 PetscInt nheight,nwidth,oheight,owidth;
3331 ierr = PCGetOperators(pc,&C,NULL); PCHKERRQ(pc,ierr);
3332 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
3333 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
3334 if (nheight != oheight || nwidth != owidth)
3338 ierr = PCReset(pc); PCHKERRQ(pc,ierr);
3344 ierr = PCSetOperators(pc,pA->
A,pA->
A); PCHKERRQ(
obj,ierr);
3353 if (delete_pA) {
delete pA; };
3356void PetscPreconditioner::MultKernel(
const Vector &
b,
Vector &x,
3360 "Iterative mode not supported for PetscPreconditioner");
3366 ierr = PCGetOperators(pc, NULL, &pA); PCHKERRQ(
obj, ierr);
3374 PetscParMatrix A(pA,
true);
3375 X =
new PetscParVector(A,
false,
false);
3386 ierr = PCApplyTranspose(pc,
B->
x,
X->
x); PCHKERRQ(pc, ierr);
3390 ierr = PCApply(pc,
B->
x,
X->
x); PCHKERRQ(pc, ierr);
3398 (*this).MultKernel(
b,x,
false);
3403 (*this).MultKernel(
b,x,
true);
3410 ierr = PetscObjectGetComm((
PetscObject)pc,&comm); PCHKERRQ(pc,ierr);
3411 ierr = PCDestroy(&pc); CCHKERRQ(comm,ierr);
3422void PetscBDDCSolver::BDDCSolverConstructor(
const PetscBDDCSolverParams &opts)
3424 MPI_Comm comm = PetscObjectComm(
obj);
3429 ierr = PCGetOperators(pc,NULL,&pA); PCHKERRQ(pc,ierr);
3433 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATIS,&ismatis);
3435 MFEM_VERIFY(ismatis,
"PetscBDDCSolver needs the matrix in unassembled format");
3438 ParFiniteElementSpace *fespace = opts.fespace;
3439 if (opts.netflux && !fespace)
3441 MFEM_WARNING(
"Don't know how to compute an auxiliary quadrature form without a ParFiniteElementSpace");
3448 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(comm,ierr);
3449 ierr = MatNullSpaceCreate(PetscObjectComm((
PetscObject)lA),PETSC_TRUE,0,NULL,
3450 &nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
3451 ierr = MatSetNearNullSpace(lA,nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
3452 ierr = MatNullSpaceDestroy(&nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
3456 ierr = PCSetType(pc,PCBDDC); PCHKERRQ(
obj,ierr);
3459 ierr = MatGetOwnershipRange(pA,&rst,NULL); PCHKERRQ(pA,ierr);
3460 ierr = MatGetLocalSize(pA,&nl,NULL); PCHKERRQ(pA,ierr);
3469 int vdim = fespace->GetVDim();
3476 ierr = MatSetBlockSize(pA,vdim); PCHKERRQ(pA,ierr);
3477 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(PETSC_COMM_SELF,ierr);
3478 ierr = MatSetBlockSize(lA,vdim); PCHKERRQ(pA,ierr);
3487 ierr = PetscMalloc1(nf,&fields); CCHKERRQ(PETSC_COMM_SELF,ierr);
3500 ierr = ISCreateStride(comm,nlf,st,bs,&fields[i]); CCHKERRQ(comm,ierr);
3506 const FiniteElementCollection *fec = fespace->FEColl();
3507 bool h1space =
dynamic_cast<const H1_FECollection*
>(fec);
3510 ParFiniteElementSpace *fespace_coords = fespace;
3512 sdim = fespace->GetParMesh()->SpaceDimension();
3515 fespace_coords =
new ParFiniteElementSpace(fespace->GetParMesh(),fec,sdim,
3518 VectorFunctionCoefficient coeff_coords(sdim, func_coords);
3519 ParGridFunction gf_coords(fespace_coords);
3520 gf_coords.ProjectCoefficient(coeff_coords);
3521 HypreParVector *hvec_coords = gf_coords.ParallelProject();
3523 hvec_coords->Size(),
false);
3531 Vec pvec_coords,lvec_coords;
3532 ISLocalToGlobalMapping l2g;
3538 ierr = VecCreateMPIWithArray(comm,sdim,hvec_coords->Size(),
3539 hvec_coords->GlobalSize(),data_coords,&pvec_coords);
3540 CCHKERRQ(comm,ierr);
3541 ierr = MatGetNearNullSpace(pA,&nnsp); CCHKERRQ(comm,ierr);
3544 ierr = MatNullSpaceCreateRigidBody(pvec_coords,&nnsp);
3545 CCHKERRQ(comm,ierr);
3546 ierr = MatSetNearNullSpace(pA,nnsp); CCHKERRQ(comm,ierr);
3547 ierr = MatNullSpaceDestroy(&nnsp); CCHKERRQ(comm,ierr);
3549 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(comm,ierr);
3550 ierr = MatCreateVecs(lA,&lvec_coords,NULL); CCHKERRQ(PETSC_COMM_SELF,ierr);
3551 ierr = VecSetBlockSize(lvec_coords,sdim); CCHKERRQ(PETSC_COMM_SELF,ierr);
3552 ierr = MatGetLocalToGlobalMapping(pA,&l2g,NULL); CCHKERRQ(comm,ierr);
3553 ierr = MatGetLayouts(pA,&rmap,NULL); CCHKERRQ(comm,ierr);
3554 ierr = PetscSFCreate(comm,&sf); CCHKERRQ(comm,ierr);
3555 ierr = ISLocalToGlobalMappingGetIndices(l2g,&gidxs); CCHKERRQ(comm,ierr);
3556 ierr = ISLocalToGlobalMappingGetSize(l2g,&nleaves); CCHKERRQ(comm,ierr);
3557 ierr = PetscSFSetGraphLayout(sf,rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);
3558 CCHKERRQ(comm,ierr);
3559 ierr = ISLocalToGlobalMappingRestoreIndices(l2g,&gidxs); CCHKERRQ(comm,ierr);
3564 ierr = VecGetArrayRead(pvec_coords,&garray); CCHKERRQ(PETSC_COMM_SELF,ierr);
3565 ierr = VecGetArray(lvec_coords,&larray); CCHKERRQ(PETSC_COMM_SELF,ierr);
3566#if PETSC_VERSION_LT(3,15,0)
3567 ierr = PetscSFBcastBegin(sf,MPIU_SCALAR,garray,larray); CCHKERRQ(comm,ierr);
3568 ierr = PetscSFBcastEnd(sf,MPIU_SCALAR,garray,larray); CCHKERRQ(comm,ierr);
3570 ierr = PetscSFBcastBegin(sf,MPIU_SCALAR,garray,larray,MPI_REPLACE);
3571 CCHKERRQ(comm,ierr);
3572 ierr = PetscSFBcastEnd(sf,MPIU_SCALAR,garray,larray,MPI_REPLACE);
3573 CCHKERRQ(comm,ierr);
3575 ierr = VecRestoreArrayRead(pvec_coords,&garray); CCHKERRQ(PETSC_COMM_SELF,ierr);
3576 ierr = VecRestoreArray(lvec_coords,&larray); CCHKERRQ(PETSC_COMM_SELF,ierr);
3578 ierr = VecDestroy(&pvec_coords); CCHKERRQ(comm,ierr);
3579 ierr = MatNullSpaceCreateRigidBody(lvec_coords,&nnsp);
3580 CCHKERRQ(PETSC_COMM_SELF,ierr);
3581 ierr = VecDestroy(&lvec_coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
3582 ierr = MatSetNearNullSpace(lA,nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
3583 ierr = MatNullSpaceDestroy(&nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
3584 ierr = PetscSFDestroy(&sf); CCHKERRQ(PETSC_COMM_SELF,ierr);
3588 ierr = PetscMalloc1(nl*sdim,&coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
3597 ierr = ISGetLocalSize(fields[i],&nn); CCHKERRQ(comm,ierr);
3598 ierr = ISGetIndices(fields[i],&idxs); CCHKERRQ(comm,ierr);
3602 for (
PetscInt d = 0; d < sdim; d++)
3604 coords[sdim*idx+d] = PetscRealPart(data_coords[sdim*j+d]);
3607 ierr = ISRestoreIndices(fields[i],&idxs); CCHKERRQ(comm,ierr);
3612 for (
PetscInt j = 0; j < nl*sdim; j++) { coords[j] = PetscRealPart(data_coords[j]); }
3614 if (fespace_coords != fespace)
3616 delete fespace_coords;
3623 IS dir = NULL, neu = NULL;
3626 Array<Mat> *l2l = NULL;
3627 if (opts.ess_dof_local || opts.nat_dof_local)
3632 MFEM_VERIFY(c,
"Local-to-local PETSc container not present");
3633 ierr = PetscContainerGetPointer(c,(
void**)&l2l); PCHKERRQ(c,ierr);
3640 PetscBool lpr = PETSC_FALSE,pr;
3641 if (opts.ess_dof) { lpr = PETSC_TRUE; }
3642 mpiierr = MPI_Allreduce(&lpr,&pr,1,MPIU_BOOL,MPI_LOR,comm);
3643 CCHKERRQ(comm,mpiierr);
3644 MFEM_VERIFY(lpr == pr,
"ess_dof should be collectively set");
3646 if (opts.nat_dof) { lpr = PETSC_TRUE; }
3647 mpiierr = MPI_Allreduce(&lpr,&pr,1,MPIU_BOOL,MPI_LOR,comm);
3648 CCHKERRQ(comm,mpiierr);
3649 MFEM_VERIFY(lpr == pr,
"nat_dof should be collectively set");
3652 ms[0] = -nf; ms[1] = nf;
3653 mpiierr = MPI_Allreduce(&ms,&Ms,2,MPIU_INT,MPI_MAX,comm);
3654 CCHKERRQ(comm,mpiierr);
3655 MFEM_VERIFY(-Ms[0] == Ms[1],
3656 "number of fields should be the same across processes");
3663 PetscInt st = opts.ess_dof_local ? 0 : rst;
3664 if (!opts.ess_dof_local)
3667 ierr = Convert_Array_IS(comm,
true,opts.ess_dof,st,&dir);
3668 CCHKERRQ(comm,ierr);
3669 ierr = PCBDDCSetDirichletBoundaries(pc,dir); PCHKERRQ(pc,ierr);
3674 ierr = Convert_Vmarks_IS(comm,*l2l,opts.ess_dof,st,&dir);
3675 CCHKERRQ(comm,ierr);
3676 ierr = PCBDDCSetDirichletBoundariesLocal(pc,dir); PCHKERRQ(pc,ierr);
3681 PetscInt st = opts.nat_dof_local ? 0 : rst;
3682 if (!opts.nat_dof_local)
3685 ierr = Convert_Array_IS(comm,
true,opts.nat_dof,st,&neu);
3686 CCHKERRQ(comm,ierr);
3687 ierr = PCBDDCSetNeumannBoundaries(pc,neu); PCHKERRQ(pc,ierr);
3692 ierr = Convert_Vmarks_IS(comm,*l2l,opts.nat_dof,st,&neu);
3693 CCHKERRQ(comm,ierr);
3694 ierr = PCBDDCSetNeumannBoundariesLocal(pc,neu); PCHKERRQ(pc,ierr);
3701 ierr = PCBDDCSetDofsSplitting(pc,nf,fields); PCHKERRQ(pc,ierr);
3705 ierr = ISDestroy(&fields[i]); CCHKERRQ(comm,ierr);
3707 ierr = PetscFree(fields); CCHKERRQ(PETSC_COMM_SELF,ierr);
3712 ierr = PCSetCoordinates(pc,sdim,nl,coords); PCHKERRQ(pc,ierr);
3714 ierr = PetscFree(coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
3723 const FiniteElementCollection *fec = fespace->FEColl();
3724 bool edgespace, rtspace, h1space;
3725 bool needint = opts.netflux;
3726 bool tracespace, rt_tracespace, edge_tracespace;
3728 PetscBool B_is_Trans = PETSC_FALSE;
3730 ParMesh *pmesh = (ParMesh *) fespace->GetMesh();
3731 dim = pmesh->Dimension();
3732 vdim = fespace->GetVDim();
3733 h1space =
dynamic_cast<const H1_FECollection*
>(fec);
3734 rtspace =
dynamic_cast<const RT_FECollection*
>(fec);
3735 edgespace =
dynamic_cast<const ND_FECollection*
>(fec);
3736 edge_tracespace =
dynamic_cast<const ND_Trace_FECollection*
>(fec);
3737 rt_tracespace =
dynamic_cast<const RT_Trace_FECollection*
>(fec);
3738 tracespace = edge_tracespace || rt_tracespace;
3741 if (fespace->GetNE() > 0)
3745 p = fespace->GetElementOrder(0);
3749 p = fespace->GetFaceOrder(0);
3750 if (
dim == 2) {
p++; }
3761 MFEM_WARNING(
"Tracespace case doesn't work for H(curl) and p=2,"
3762 " not using auxiliary quadrature");
3768 FiniteElementCollection *vfec;
3771 vfec =
new H1_Trace_FECollection(
p,
dim);
3775 vfec =
new H1_FECollection(
p,
dim);
3777 ParFiniteElementSpace *vfespace =
new ParFiniteElementSpace(pmesh,vfec);
3778 ParDiscreteLinearOperator *grad;
3779 grad =
new ParDiscreteLinearOperator(vfespace,fespace);
3782 grad->AddTraceFaceInterpolator(
new GradientInterpolator);
3786 grad->AddDomainInterpolator(
new GradientInterpolator);
3790 HypreParMatrix *hG = grad->ParallelAssemble();
3791 PetscParMatrix *G =
new PetscParMatrix(hG,
PETSC_MATAIJ);
3795 PetscBool conforming = PETSC_TRUE;
3796 if (pmesh->Nonconforming()) { conforming = PETSC_FALSE; }
3797 ierr = PCBDDCSetDiscreteGradient(pc,*G,
p,0,PETSC_TRUE,conforming);
3809 MFEM_WARNING(
"Tracespace case doesn't work for H(div), not using"
3810 " auxiliary quadrature");
3816 if (vdim !=
dim) { needint =
false; }
3819 PetscParMatrix *
B = NULL;
3825 FiniteElementCollection *auxcoll;
3826 if (tracespace) { auxcoll =
new RT_Trace_FECollection(
p,
dim); }
3831 auxcoll =
new H1_FECollection(std::max(
p-1,1),
dim);
3835 auxcoll =
new L2_FECollection(
p,
dim);
3838 ParFiniteElementSpace *pspace =
new ParFiniteElementSpace(pmesh,auxcoll);
3839 ParMixedBilinearForm *
b =
new ParMixedBilinearForm(fespace,pspace);
3845 b->AddTraceFaceIntegrator(
new VectorFECurlIntegrator);
3849 b->AddDomainIntegrator(
new VectorFECurlIntegrator);
3856 b->AddTraceFaceIntegrator(
new VectorFEDivergenceIntegrator);
3860 b->AddDomainIntegrator(
new VectorFEDivergenceIntegrator);
3865 b->AddDomainIntegrator(
new VectorDivergenceIntegrator);
3870 b->ParallelAssemble(Bh);
3872 Bh.SetOperatorOwner(
false);
3877 ierr = MatTranspose(pB,MAT_INPLACE_MATRIX,&pB); PCHKERRQ(pA,ierr);
3878 if (!opts.ess_dof_local)
3880 ierr = MatZeroRowsIS(pB,dir,0.,NULL,NULL); PCHKERRQ(pA,ierr);
3884 ierr = MatZeroRowsLocalIS(pB,dir,0.,NULL,NULL); PCHKERRQ(pA,ierr);
3886 B_is_Trans = PETSC_TRUE;
3895 ierr = PCBDDCSetDivergenceMat(pc,*
B,B_is_Trans,NULL); PCHKERRQ(pc,ierr);
3899 ierr = ISDestroy(&dir); PCHKERRQ(pc,ierr);
3900 ierr = ISDestroy(&neu); PCHKERRQ(pc,ierr);
3905 const std::string &prefix)
3908 BDDCSolverConstructor(opts);
3914 const std::string &prefix)
3917 BDDCSolverConstructor(opts);
3922 const string &prefix)
3926 ierr = PCSetType(pc,PCFIELDSPLIT); PCHKERRQ(pc,ierr);
3929 ierr = PCGetOperators(pc,&pA,NULL); PCHKERRQ(pc,ierr);
3933 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATNEST,&isnest);
3939 ierr = MatNestGetSize(pA,&nr,NULL); PCHKERRQ(pc,ierr);
3940 ierr = PetscCalloc1(nr,&isrow); CCHKERRQ(PETSC_COMM_SELF,ierr);
3941 ierr = MatNestGetISs(pA,isrow,NULL); PCHKERRQ(pc,ierr);
3951 ierr = PCFieldSplitSetIS(pc,NULL,isrow[i]); PCHKERRQ(pc,ierr);
3953 ierr = PetscFree(isrow); CCHKERRQ(PETSC_COMM_SELF,ierr);
3958 const std::string &prefix)
3962 ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE); PCHKERRQ(A,ierr);
3963 ierr = MatSetOption(A,MAT_SYMMETRY_ETERNAL,PETSC_TRUE); PCHKERRQ(A,ierr);
3965 H2SolverConstructor(fes);
3971#if defined(PETSC_HAVE_H2OPUS)
3983 VectorFunctionCoefficient ccoords(sdim, func_coords);
3985 ParGridFunction coords(fes);
3986 coords.ProjectCoefficient(ccoords);
3988 coords.ParallelProject(c);
3992 ierr = PCSetType(pc,PCH2OPUS); PCHKERRQ(
obj, ierr);
3993 ierr = PCSetCoordinates(pc,sdim,c.Size()/sdim,
3996 ierr = PCSetFromOptions(pc); PCHKERRQ(
obj, ierr);
3998 MFEM_ABORT(
"Need PETSc configured with --download-h2opus");
4005 const std::string &prefix)
4010 ierr = SNESCreate(comm, &snes); CCHKERRQ(comm, ierr);
4012 ierr = PetscObjectGetClassId(
obj, &
cid); PCHKERRQ(
obj, ierr);
4013 ierr = SNESSetOptionsPrefix(snes, prefix.c_str()); PCHKERRQ(snes, ierr);
4020 const std::string &prefix)
4025 ierr = SNESCreate(comm, &snes); CCHKERRQ(comm, ierr);
4027 ierr = PetscObjectGetClassId(
obj, &
cid); PCHKERRQ(
obj, ierr);
4028 ierr = SNESSetOptionsPrefix(snes, prefix.c_str()); PCHKERRQ(snes, ierr);
4040 ierr = PetscObjectGetComm(
obj,&comm); PCHKERRQ(
obj, ierr);
4041 ierr = SNESDestroy(&snes); CCHKERRQ(comm, ierr);
4053 ierr = SNESGetFunction(snes, NULL, NULL, &fctx);
4054 PCHKERRQ(snes, ierr);
4055 ierr = SNESGetJacobian(snes, NULL, NULL, NULL, &jctx);
4056 PCHKERRQ(snes, ierr);
4059 (
void*)&op == fctx &&
4060 (
void*)&op == jctx);
4061 mpiierr = MPI_Allreduce(&ls,&gs,1,MPIU_BOOL,MPI_LAND,
4063 CCHKERRQ(PetscObjectComm((
PetscObject)snes),mpiierr);
4066 ierr = SNESReset(snes); PCHKERRQ(snes,ierr);
4077 ierr = SNESGetLineSearch(snes, &ls); PCHKERRQ(snes,ierr);
4078 ierr = SNESLineSearchSetType(ls, SNESLINESEARCHBT); PCHKERRQ(snes,ierr);
4087 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
4089 ierr = SNESSetFunction(snes, NULL, __mfem_snes_function, (
void *)snes_ctx);
4090 PCHKERRQ(snes, ierr);
4091 ierr = SNESSetJacobian(snes, dummy, dummy, __mfem_snes_jacobian,
4093 PCHKERRQ(snes, ierr);
4095 ierr = MatDestroy(&dummy);
4096 PCHKERRQ(snes, ierr);
4108 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
4109 snes_ctx->jacType = jacType;
4115 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
4116 snes_ctx->objective = objfn;
4119 ierr = SNESSetObjective(snes, __mfem_snes_objective, (
void *)snes_ctx);
4120 PCHKERRQ(snes, ierr);
4127 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
4128 snes_ctx->postcheck = post;
4132 ierr = SNESGetLineSearch(snes, &ls); PCHKERRQ(snes,ierr);
4133 ierr = SNESLineSearchSetPostCheck(ls, __mfem_snes_postcheck, (
void *)snes_ctx);
4143 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
4144 snes_ctx->update = update;
4147 ierr = SNESSetUpdate(snes, __mfem_snes_update); PCHKERRQ(snes, ierr);
4154 bool b_nonempty =
b.Size();
4166 ierr = SNESSolve(snes,
B->
x,
X->
x); PCHKERRQ(snes, ierr);
4178 ierr = TSCreate(comm,&ts); CCHKERRQ(comm,ierr);
4180 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
4181 ierr = TSSetOptionsPrefix(ts, prefix.c_str()); PCHKERRQ(ts, ierr);
4187 ierr = TSSetMaxSteps(ts,PETSC_MAX_INT-1);
4189 ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);
4192 ierr = TSGetAdapt(ts,&tsad);
4194 ierr = TSAdaptSetType(tsad,TSADAPTNONE);
4202 ierr = PetscObjectGetComm(
obj,&comm); PCHKERRQ(
obj,ierr);
4203 ierr = TSDestroy(&ts); CCHKERRQ(comm,ierr);
4211 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
4214 ierr = TSReset(ts); PCHKERRQ(ts,ierr);
4217 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
4218 ts_ctx->cached_ijacstate = -1;
4219 ts_ctx->cached_rhsjacstate = -1;
4220 ts_ctx->cached_splits_xstate = -1;
4221 ts_ctx->cached_splits_xdotstate = -1;
4233 ierr = TSSetIFunction(ts, NULL, __mfem_ts_ifunction, (
void *)ts_ctx);
4235 ierr = TSSetIJacobian(ts, dummy, dummy, __mfem_ts_ijacobian, (
void *)ts_ctx);
4237 ierr = TSSetEquationType(ts, TS_EQ_IMPLICIT);
4239 ierr = MatDestroy(&dummy);
4247 ierr = TSSetEquationType(ts, TS_EQ_EXPLICIT);
4256 ierr = TSSetRHSFunction(ts, NULL, __mfem_ts_rhsfunction, (
void *)ts_ctx);
4258 ierr = TSSetRHSJacobian(ts, dummy, dummy, __mfem_ts_rhsjacobian,
4261 ierr = MatDestroy(&dummy);
4270 ierr = TSSetSolution(ts,
X); PCHKERRQ(ts,ierr);
4273 PetscBool use = PETSC_TRUE;
4274 ierr = PetscOptionsGetBool(NULL,NULL,
"-mfem_use_splitjac",&use,NULL);
4277 ierr = PetscObjectComposeFunction((
PetscObject)ts,
"TSComputeSplitJacobians_C",
4278 __mfem_ts_computesplits);
4283 ierr = PetscObjectComposeFunction((
PetscObject)ts,
"TSComputeSplitJacobians_C",
4291 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
4292 ts_ctx->jacType = jacType;
4297 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
4298 return ts_ctx->type;
4303 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
4306 ts_ctx->type = type;
4309 ierr = TSSetProblemType(ts, TS_LINEAR);
4314 ierr = TSSetProblemType(ts, TS_NONLINEAR);
4323 ierr = TSSetTime(ts, t); PCHKERRQ(ts, ierr);
4324 ierr = TSSetTimeStep(ts, dt); PCHKERRQ(ts, ierr);
4327 ierr = TSGetStepNumber(ts, &i); PCHKERRQ(ts,ierr);
4337 ierr = TSMonitor(ts, i, t, *
X); PCHKERRQ(ts,ierr);
4341 ierr = TSSetSolution(ts, *
X); PCHKERRQ(ts, ierr);
4342 ierr = TSStep(ts); PCHKERRQ(ts, ierr);
4347 ierr = TSGetTime(ts, &pt); PCHKERRQ(ts,ierr);
4352 ierr = TSMonitor(ts, i+1, pt, *
X); PCHKERRQ(ts,ierr);
4362 ierr = TSSetTime(ts, t); PCHKERRQ(ts, ierr);
4363 ierr = TSSetTimeStep(ts, dt); PCHKERRQ(ts, ierr);
4364 ierr = TSSetMaxTime(ts, t_final); PCHKERRQ(ts, ierr);
4365 ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
4377 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
4378 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
4379 ts_ctx->cached_ijacstate = -1;
4380 ts_ctx->cached_rhsjacstate = -1;
4381 ts_ctx->cached_splits_xstate = -1;
4382 ts_ctx->cached_splits_xdotstate = -1;
4385 ierr = TSSolve(ts,
X->
x); PCHKERRQ(ts, ierr);
4390 ierr = TSGetTime(ts, &pt); PCHKERRQ(ts,ierr);
4392 ierr = TSGetTimeStep(ts,&pt); PCHKERRQ(ts,ierr);
4398#include "petsc/private/petscimpl.h"
4399#include "petsc/private/matimpl.h"
4405 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)
ctx;
4407 PetscFunctionBeginUser;
4410 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
4422 PetscFunctionReturn(PETSC_SUCCESS);
4425static PetscErrorCode __mfem_ts_ifunction(TS ts,
PetscReal t, Vec x, Vec xp,
4428 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
ctx;
4430 PetscFunctionBeginUser;
4438 if (ts_ctx->bchandler)
4443 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(xx.Size()); }
4444 if (!ts_ctx->work2) { ts_ctx->work2 =
new mfem::Vector(xx.Size()); }
4450 bchandler->
ZeroBC(yy,*txp);
4460 ff.UpdateVecFromFlags();
4461 PetscFunctionReturn(PETSC_SUCCESS);
4464static PetscErrorCode __mfem_ts_rhsfunction(TS ts,
PetscReal t, Vec x, Vec
f,
4467 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
ctx;
4469 PetscFunctionBeginUser;
4470 if (ts_ctx->bchandler) { MFEM_ABORT(
"RHS evaluation with bc not implemented"); }
4479 ff.UpdateVecFromFlags();
4480 PetscFunctionReturn(PETSC_SUCCESS);
4483static PetscErrorCode __mfem_ts_ijacobian(TS ts,
PetscReal t, Vec x,
4487 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
ctx;
4492 PetscObjectState state;
4493 PetscErrorCode ierr;
4495 PetscFunctionBeginUser;
4499 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4500 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4506 ierr = PetscObjectStateGet((
PetscObject)P,&state); CHKERRQ(ierr);
4508 std::abs(ts_ctx->cached_shift/shift - 1.0) < eps &&
4509 state == ts_ctx->cached_ijacstate) { PetscFunctionReturn(PETSC_SUCCESS); }
4516 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4517 ierr = VecGetArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
4519 ierr = VecRestoreArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
4520 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4521 if (!ts_ctx->bchandler)
4528 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
4535 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4539 if (!ts_ctx->bchandler) {
delete xx; }
4540 ts_ctx->cached_shift = shift;
4543 bool delete_pA =
false;
4547 pA->
GetType() != ts_ctx->jacType))
4555 if (ts_ctx->bchandler)
4563 PetscObjectState nonzerostate;
4564 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
4569 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
4570 if (delete_pA) {
delete pA; }
4582 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
4584 if (isnest) { P->nonzerostate = nonzerostate + 1; }
4587 ierr = PetscObjectStateGet((
PetscObject)P,&ts_ctx->cached_ijacstate);
4593 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
4594 ierr = TSGetDM(ts,&dm); CHKERRQ(ierr);
4595 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
4596 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
4597 PetscFunctionReturn(PETSC_SUCCESS);
4600static PetscErrorCode __mfem_ts_computesplits(TS ts,
PetscReal t,Vec x,Vec xp,
4604 __mfem_ts_ctx* ts_ctx;
4608 PetscObjectState state;
4609 PetscBool rx = PETSC_TRUE, rxp = PETSC_TRUE;
4610 PetscBool assembled;
4611 PetscErrorCode ierr;
4613 PetscFunctionBeginUser;
4617 ierr = MatAssemblyBegin(Ax,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4618 ierr = MatAssemblyEnd(Ax,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4620 if (Axp && Axp != Jxp)
4622 ierr = MatAssemblyBegin(Axp,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4623 ierr = MatAssemblyEnd(Axp,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4626 ierr = TSGetIJacobian(ts,NULL,NULL,NULL,(
void**)&ts_ctx); CHKERRQ(ierr);
4629 ierr = PetscObjectStateGet((
PetscObject)Jx,&state); CHKERRQ(ierr);
4631 state == ts_ctx->cached_splits_xstate) { rx = PETSC_FALSE; }
4632 ierr = PetscObjectStateGet((
PetscObject)Jxp,&state); CHKERRQ(ierr);
4634 state == ts_ctx->cached_splits_xdotstate) { rxp = PETSC_FALSE; }
4635 if (!rx && !rxp) { PetscFunctionReturn(PETSC_SUCCESS); }
4642 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4643 ierr = VecGetArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
4645 ierr = VecRestoreArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
4646 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4647 if (!ts_ctx->bchandler)
4654 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
4661 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4670 bool delete_mat =
false;
4674 pJx->
GetType() != ts_ctx->jacType))
4679 ierr = PetscObjectReference((
PetscObject)B); CHKERRQ(ierr);
4687 ierr = MatAssembled(Jx,&assembled); CHKERRQ(ierr);
4690 ierr = MatCopy(*pJx,Jx,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
4695 ierr = MatDuplicate(*pJx,MAT_COPY_VALUES,&B); CHKERRQ(ierr);
4696 ierr = MatHeaderReplace(Jx,&B); CHKERRQ(ierr);
4699 if (delete_mat) {
delete pJx; }
4703 if (ts_ctx->bchandler)
4720 pJxp->
GetType() != ts_ctx->jacType))
4725 ierr = PetscObjectReference((
PetscObject)B); CHKERRQ(ierr);
4728 &oJxp,ts_ctx->jacType);
4732 ierr = MatAssembled(Jxp,&assembled); CHKERRQ(ierr);
4735 ierr = MatCopy(*pJxp,Jxp,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
4740 ierr = MatDuplicate(*pJxp,MAT_COPY_VALUES,&B); CHKERRQ(ierr);
4741 ierr = MatHeaderReplace(Jxp,&B); CHKERRQ(ierr);
4743 if (delete_mat) {
delete pJxp; }
4747 if (ts_ctx->bchandler)
4758 ierr = MatAXPY(*pJxp,-1.0,*pJx,SAME_NONZERO_PATTERN); PCHKERRQ(ts,ierr);
4762 ierr = PetscObjectStateGet((
PetscObject)Jx,&ts_ctx->cached_splits_xstate);
4764 ierr = PetscObjectStateGet((
PetscObject)Jxp,&ts_ctx->cached_splits_xdotstate);
4769 if (!ts_ctx->bchandler) {
delete xx; }
4770 PetscFunctionReturn(PETSC_SUCCESS);
4773static PetscErrorCode __mfem_ts_rhsjacobian(TS ts,
PetscReal t, Vec x,
4774 Mat A, Mat P,
void *
ctx)
4776 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
ctx;
4780 PetscObjectState state;
4781 PetscErrorCode ierr;
4783 PetscFunctionBeginUser;
4787 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4788 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4792 ierr = PetscObjectStateGet((
PetscObject)P,&state); CHKERRQ(ierr);
4794 state == ts_ctx->cached_rhsjacstate) { PetscFunctionReturn(PETSC_SUCCESS); }
4801 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4802 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4803 if (!ts_ctx->bchandler)
4810 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
4817 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4821 if (!ts_ctx->bchandler) {
delete xx; }
4824 bool delete_pA =
false;
4828 pA->
GetType() != ts_ctx->jacType))
4836 if (ts_ctx->bchandler)
4844 PetscObjectState nonzerostate;
4845 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
4850 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
4851 if (delete_pA) {
delete pA; }
4863 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
4865 if (isnest) { P->nonzerostate = nonzerostate + 1; }
4870 ierr = TSRHSJacobianSetReuse(ts,PETSC_TRUE); PCHKERRQ(ts,ierr);
4872 ierr = PetscObjectStateGet((
PetscObject)P,&ts_ctx->cached_rhsjacstate);
4878 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
4879 ierr = TSGetDM(ts,&dm); CHKERRQ(ierr);
4880 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
4881 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
4882 PetscFunctionReturn(PETSC_SUCCESS);
4888 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)
ctx;
4890 PetscFunctionBeginUser;
4893 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
4902 PetscErrorCode ierr;
4904 ierr = SNESGetSolution(snes,&x); CHKERRQ(ierr);
4911 PetscErrorCode ierr;
4913 ierr = SNESGetFunction(snes,&x,NULL,NULL); CHKERRQ(ierr);
4918 PetscFunctionReturn(PETSC_SUCCESS);
4921static PetscErrorCode __mfem_snes_jacobian(SNES snes, Vec x, Mat A, Mat P,
4926 PetscErrorCode ierr;
4928 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
ctx;
4930 PetscFunctionBeginUser;
4931 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4932 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4933 if (!snes_ctx->bchandler)
4940 if (!snes_ctx->work) { snes_ctx->work =
new mfem::Vector(n); }
4943 xx = snes_ctx->work;
4949 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4950 if (!snes_ctx->bchandler) {
delete xx; }
4953 bool delete_pA =
false;
4957 pA->
GetType() != snes_ctx->jacType))
4965 if (snes_ctx->bchandler)
4973 PetscObjectState nonzerostate;
4974 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
4978 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
4979 if (delete_pA) {
delete pA; }
4991 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
4993 if (isnest) { P->nonzerostate = nonzerostate + 1; }
4998 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4999 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5005 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
5006 ierr = SNESGetDM(snes,&dm); CHKERRQ(ierr);
5007 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
5008 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
5009 PetscFunctionReturn(PETSC_SUCCESS);
5012static PetscErrorCode __mfem_snes_function(SNES snes, Vec x, Vec
f,
void *
ctx)
5014 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)
ctx;
5016 PetscFunctionBeginUser;
5019 if (snes_ctx->bchandler)
5026 snes_ctx->op->
Mult(*txx,ff);
5033 snes_ctx->op->
Mult(xx,ff);
5035 ff.UpdateVecFromFlags();
5036 PetscFunctionReturn(PETSC_SUCCESS);
5039static PetscErrorCode __mfem_snes_objective(SNES snes, Vec x,
PetscReal *
f,
5042 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)
ctx;
5044 PetscFunctionBeginUser;
5045 if (!snes_ctx->objective)
5047 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing objective function");
5051 (*snes_ctx->objective)(snes_ctx->op,xx,&lf);
5053 PetscFunctionReturn(PETSC_SUCCESS);
5056static PetscErrorCode __mfem_snes_postcheck(SNESLineSearch ls,Vec X,Vec Y,Vec W,
5057 PetscBool *cy,PetscBool *cw,
void*
ctx)
5059 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)
ctx;
5060 bool lcy =
false,lcw =
false;
5062 PetscFunctionBeginUser;
5066 (*snes_ctx->postcheck)(snes_ctx->op,x,y,w,lcy,lcw);
5067 if (lcy) { y.UpdateVecFromFlags(); *cy = PETSC_TRUE; }
5068 if (lcw) { w.UpdateVecFromFlags(); *cw = PETSC_TRUE; }
5069 PetscFunctionReturn(PETSC_SUCCESS);
5072static PetscErrorCode __mfem_snes_update(SNES snes,
PetscInt it)
5075 __mfem_snes_ctx* snes_ctx;
5077 PetscFunctionBeginUser;
5079 ierr = SNESGetFunction(snes,&F,NULL,(
void **)&snes_ctx); CHKERRQ(ierr);
5080 ierr = SNESGetSolution(snes,&X); CHKERRQ(ierr);
5083 ierr = VecDuplicate(X,&pX); CHKERRQ(ierr);
5086 ierr = VecDestroy(&pX); CHKERRQ(ierr);
5090 if (!pX) SETERRQ(PetscObjectComm((
PetscObject)snes),PETSC_ERR_USER,
5091 "Missing previous solution");
5092 ierr = SNESGetSolutionUpdate(snes,&dX); CHKERRQ(ierr);
5097 (*snes_ctx->update)(snes_ctx->op,it,
f,x,dx,px);
5099 ierr = VecCopy(X,pX); CHKERRQ(ierr);
5100 PetscFunctionReturn(PETSC_SUCCESS);
5106 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)
ctx;
5108 PetscFunctionBeginUser;
5111 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
5120 PetscErrorCode ierr;
5122 ierr = KSPBuildSolution(ksp,NULL,&x); CHKERRQ(ierr);
5129 PetscErrorCode ierr;
5131 ierr = KSPBuildResidual(ksp,NULL,NULL,&x); CHKERRQ(ierr);
5136 PetscFunctionReturn(PETSC_SUCCESS);
5139static PetscErrorCode __mfem_mat_shell_apply(Mat A, Vec x, Vec y)
5142 PetscErrorCode ierr;
5144 PetscFunctionBeginUser;
5145 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
5146 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
5150 yy.UpdateVecFromFlags();
5151 PetscFunctionReturn(PETSC_SUCCESS);
5154static PetscErrorCode __mfem_mat_shell_apply_transpose(Mat A, Vec x, Vec y)
5157 PetscErrorCode ierr;
5160 PetscFunctionBeginUser;
5161 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
5162 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
5165 ierr = MatIsSymmetricKnown(A,&flg,&symm); CHKERRQ(ierr);
5174 yy.UpdateVecFromFlags();
5175 PetscFunctionReturn(PETSC_SUCCESS);
5178static PetscErrorCode __mfem_mat_shell_copy(Mat A, Mat B, MatStructure str)
5181 PetscErrorCode ierr;
5183 PetscFunctionBeginUser;
5184 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
5185 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
5186 ierr = MatShellSetContext(B,(
void *)op); CHKERRQ(ierr);
5187 PetscFunctionReturn(PETSC_SUCCESS);
5190static PetscErrorCode __mfem_mat_shell_destroy(Mat A)
5192 PetscFunctionBeginUser;
5193 PetscFunctionReturn(PETSC_SUCCESS);
5196static PetscErrorCode __mfem_pc_shell_view(PC pc, PetscViewer viewer)
5198 __mfem_pc_shell_ctx *
ctx;
5199 PetscErrorCode ierr;
5201 PetscFunctionBeginUser;
5202 ierr = PCShellGetContext(pc,(
void **)&
ctx); CHKERRQ(ierr);
5206 ierr = PetscObjectTypeCompare((
PetscObject)viewer,PETSCVIEWERASCII,&isascii);
5213 ierr = PCView(*ppc,viewer); CHKERRQ(ierr);
5219 ierr = PetscViewerASCIIPrintf(viewer,
5220 "No information available on the mfem::Solver\n");
5224 if (isascii &&
ctx->factory)
5226 ierr = PetscViewerASCIIPrintf(viewer,
5227 "Number of preconditioners created by the factory %lu\n",
ctx->numprec);
5231 PetscFunctionReturn(PETSC_SUCCESS);
5234static PetscErrorCode __mfem_pc_shell_apply(PC pc, Vec x, Vec y)
5236 __mfem_pc_shell_ctx *
ctx;
5237 PetscErrorCode ierr;
5239 PetscFunctionBeginUser;
5242 ierr = PCShellGetContext(pc,(
void **)&
ctx); CHKERRQ(ierr);
5245 ctx->op->Mult(xx,yy);
5246 yy.UpdateVecFromFlags();
5252 PetscFunctionReturn(PETSC_SUCCESS);
5255static PetscErrorCode __mfem_pc_shell_apply_transpose(PC pc, Vec x, Vec y)
5257 __mfem_pc_shell_ctx *
ctx;
5258 PetscErrorCode ierr;
5260 PetscFunctionBeginUser;
5263 ierr = PCShellGetContext(pc,(
void **)&
ctx); CHKERRQ(ierr);
5266 ctx->op->MultTranspose(xx,yy);
5267 yy.UpdateVecFromFlags();
5273 PetscFunctionReturn(PETSC_SUCCESS);
5276static PetscErrorCode __mfem_pc_shell_setup(PC pc)
5278 __mfem_pc_shell_ctx *
ctx;
5280 PetscFunctionBeginUser;
5281 ierr = PCShellGetContext(pc,(
void **)&
ctx); CHKERRQ(ierr);
5292 ierr = PCGetOperators(pc,NULL,&B); CHKERRQ(ierr);
5301 PetscFunctionReturn(PETSC_SUCCESS);
5304static PetscErrorCode __mfem_pc_shell_destroy(PC pc)
5306 __mfem_pc_shell_ctx *
ctx;
5307 PetscErrorCode ierr;
5309 PetscFunctionBeginUser;
5310 ierr = PCShellGetContext(pc,(
void **)&
ctx); CHKERRQ(ierr);
5316 PetscFunctionReturn(PETSC_SUCCESS);
5319#if PETSC_VERSION_LT(3,23,0)
5321static PetscErrorCode __mfem_array_container_destroy(
void *ptr)
5323 PetscErrorCode ierr;
5325 PetscFunctionBeginUser;
5326 ierr = PetscFree(ptr); CHKERRQ(ierr);
5327 PetscFunctionReturn(PETSC_SUCCESS);
5330static PetscErrorCode __mfem_matarray_container_destroy(
void *ptr)
5333 PetscErrorCode ierr;
5335 PetscFunctionBeginUser;
5336 for (
int i=0; i<
a->Size(); i++)
5340 ierr = MatDestroy(&M); CCHKERRQ(comm,ierr);
5343 PetscFunctionReturn(PETSC_SUCCESS);
5348static PetscErrorCode __mfem_array_container_destroy(
void **ptr)
5350 PetscErrorCode ierr;
5352 PetscFunctionBeginUser;
5353 ierr = PetscFree(*ptr); CHKERRQ(ierr);
5354 PetscFunctionReturn(PETSC_SUCCESS);
5357static PetscErrorCode __mfem_matarray_container_destroy(
void **ptr)
5360 PetscErrorCode ierr;
5362 PetscFunctionBeginUser;
5363 for (
int i=0; i<
a->Size(); i++)
5367 ierr = MatDestroy(&M); CCHKERRQ(comm,ierr);
5370 PetscFunctionReturn(PETSC_SUCCESS);
5375static PetscErrorCode __mfem_monitor_ctx_destroy(
void **
ctx)
5377 PetscErrorCode ierr;
5379 PetscFunctionBeginUser;
5380 ierr = PetscFree(*
ctx); CHKERRQ(ierr);
5381 PetscFunctionReturn(PETSC_SUCCESS);
5386PetscErrorCode MakeShellPC(PC pc,
mfem::Solver &precond,
bool ownsop)
5388 PetscFunctionBeginUser;
5389 __mfem_pc_shell_ctx *
ctx =
new __mfem_pc_shell_ctx;
5391 ctx->ownsop = ownsop;
5392 ctx->factory = NULL;
5398 ierr = PCSetType(pc,PCNONE); CHKERRQ(ierr);
5400 ierr = PCSetType(pc,PCSHELL); CHKERRQ(ierr);
5401 ierr = PCShellSetName(pc,
"MFEM Solver (unknown Pmat)"); CHKERRQ(ierr);
5402 ierr = PCShellSetContext(pc,(
void *)
ctx); CHKERRQ(ierr);
5403 ierr = PCShellSetApply(pc,__mfem_pc_shell_apply); CHKERRQ(ierr);
5404 ierr = PCShellSetApplyTranspose(pc,__mfem_pc_shell_apply_transpose);
5406 ierr = PCShellSetSetUp(pc,__mfem_pc_shell_setup); CHKERRQ(ierr);
5407 ierr = PCShellSetView(pc,__mfem_pc_shell_view); CHKERRQ(ierr);
5408 ierr = PCShellSetDestroy(pc,__mfem_pc_shell_destroy); CHKERRQ(ierr);
5409 PetscFunctionReturn(PETSC_SUCCESS);
5414PetscErrorCode MakeShellPCWithFactory(PC pc,
5417 PetscFunctionBeginUser;
5418 __mfem_pc_shell_ctx *
ctx =
new __mfem_pc_shell_ctx;
5421 ctx->factory = factory;
5427 ierr = PCSetType(pc,PCNONE); CHKERRQ(ierr);
5429 ierr = PCSetType(pc,PCSHELL); CHKERRQ(ierr);
5430 ierr = PCShellSetName(pc,factory->
GetName()); CHKERRQ(ierr);
5431 ierr = PCShellSetContext(pc,(
void *)
ctx); CHKERRQ(ierr);
5432 ierr = PCShellSetApply(pc,__mfem_pc_shell_apply); CHKERRQ(ierr);
5433 ierr = PCShellSetApplyTranspose(pc,__mfem_pc_shell_apply_transpose);
5435 ierr = PCShellSetSetUp(pc,__mfem_pc_shell_setup); CHKERRQ(ierr);
5436 ierr = PCShellSetView(pc,__mfem_pc_shell_view); CHKERRQ(ierr);
5437 ierr = PCShellSetDestroy(pc,__mfem_pc_shell_destroy); CHKERRQ(ierr);
5438 PetscFunctionReturn(PETSC_SUCCESS);
5443static PetscErrorCode Convert_Array_IS(MPI_Comm comm,
bool islist,
5447 PetscInt n = list ? list->Size() : 0,*idxs;
5448 const int *data = list ? list->GetData() : NULL;
5449 PetscErrorCode ierr;
5451 PetscFunctionBeginUser;
5452 ierr = PetscMalloc1(n,&idxs); CHKERRQ(ierr);
5455 for (
PetscInt i=0; i<n; i++) { idxs[i] = data[i] + st; }
5462 if (data[i]) { idxs[cum++] = i+st; }
5466 ierr = ISCreateGeneral(comm,n,idxs,PETSC_OWN_POINTER,is);
5468 PetscFunctionReturn(PETSC_SUCCESS);
5474static PetscErrorCode Convert_Vmarks_IS(MPI_Comm comm,
5482 PetscErrorCode ierr;
5484 PetscFunctionBeginUser;
5485 for (
int i = 0; i < pl2l.
Size(); i++)
5489 ierr = MatGetRowIJ(pl2l[i],0,PETSC_FALSE,PETSC_FALSE,&m,(
const PetscInt**)&ii,
5490 (
const PetscInt**)&jj,&done); CHKERRQ(ierr);
5491 MFEM_VERIFY(done,
"Unable to perform MatGetRowIJ on " << i <<
" l2l matrix");
5492 ierr = MatGetSize(pl2l[i],NULL,&n); CHKERRQ(ierr);
5493#if defined(PETSC_USE_64BIT_INDICES)
5494 int nnz = (int)ii[m];
5495 int *mii =
new int[m+1];
5496 int *mjj =
new int[nnz];
5497 for (
int j = 0; j < m+1; j++) { mii[j] = (int)ii[j]; }
5498 for (
int j = 0; j < nnz; j++) { mjj[j] = (int)jj[j]; }
5503 ierr = MatRestoreRowIJ(pl2l[i],0,PETSC_FALSE,PETSC_FALSE,&m,
5505 (
const PetscInt**)&jj,&done); CHKERRQ(ierr);
5506 MFEM_VERIFY(done,
"Unable to perform MatRestoreRowIJ on "
5507 << i <<
" l2l matrix");
5510 for (
int i = 0; i < l2l.Size(); i++) { nl += l2l[i]->Width(); }
5512 const int* vdata = mark->
GetData();
5513 int* sdata = sub_dof_marker.
GetData();
5514 int cumh = 0, cumw = 0;
5515 for (
int i = 0; i < l2l.Size(); i++)
5520 l2l[i]->BooleanMultTranspose(vf_marker,sf_marker);
5521 cumh += l2l[i]->Height();
5522 cumw += l2l[i]->Width();
5524 ierr = Convert_Array_IS(comm,
false,&sub_dof_marker,st,is); CCHKERRQ(comm,ierr);
5525 for (
int i = 0; i < pl2l.
Size(); i++)
5529 PetscFunctionReturn(PETSC_SUCCESS);
5532#if !defined(PETSC_HAVE_HYPRE)
5534#if defined(HYPRE_MIXEDINT)
5535#error "HYPRE_MIXEDINT not supported"
5538#include "_hypre_parcsr_mv.h"
5539static PetscErrorCode MatConvert_hypreParCSR_AIJ(hypre_ParCSRMatrix* hA,Mat* pA)
5541 MPI_Comm comm = hypre_ParCSRMatrixComm(hA);
5542 hypre_CSRMatrix *hdiag,*hoffd;
5544 PetscInt *dii,*djj,*oii,*ojj,*iptr;
5547 PetscErrorCode ierr;
5549 PetscFunctionBeginUser;
5550 hdiag = hypre_ParCSRMatrixDiag(hA);
5551 hoffd = hypre_ParCSRMatrixOffd(hA);
5552 m = hypre_CSRMatrixNumRows(hdiag);
5553 n = hypre_CSRMatrixNumCols(hdiag);
5554 dnnz = hypre_CSRMatrixNumNonzeros(hdiag);
5555 onnz = hypre_CSRMatrixNumNonzeros(hoffd);
5556 ierr = PetscMalloc1(m+1,&dii); CHKERRQ(ierr);
5557 ierr = PetscMalloc1(dnnz,&djj); CHKERRQ(ierr);
5558 ierr = PetscMalloc1(dnnz,&da); CHKERRQ(ierr);
5559 ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*
sizeof(
PetscInt));
5561 ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*
sizeof(
PetscInt));
5563 ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*
sizeof(
PetscScalar));
5570 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr); CHKERRQ(ierr);
5574 ierr = MPI_Comm_size(comm,&size); CHKERRQ(ierr);
5579 ierr = PetscMalloc1(m+1,&oii); CHKERRQ(ierr);
5580 ierr = PetscMalloc1(onnz,&ojj); CHKERRQ(ierr);
5581 ierr = PetscMalloc1(onnz,&oa); CHKERRQ(ierr);
5582 ierr = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*
sizeof(
PetscInt));
5584 offdj = hypre_CSRMatrixJ(hoffd);
5585 coffd = hypre_ParCSRMatrixColMapOffd(hA);
5586 for (i=0; i<onnz; i++) { ojj[i] = coffd[offdj[i]]; }
5587 ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*
sizeof(
PetscScalar));
5594 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr); CHKERRQ(ierr);
5598 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,
5599 djj,da,oii,ojj,oa,pA); CHKERRQ(ierr);
5605 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,pA); CHKERRQ(ierr);
5611 void *ptrs[6] = {dii,djj,da,oii,ojj,oa};
5612 const char *names[6] = {
"_mfem_csr_dii",
5623 ierr = PetscContainerCreate(comm,&c); CHKERRQ(ierr);
5624 ierr = PetscContainerSetPointer(c,ptrs[i]); CHKERRQ(ierr);
5625#if PETSC_VERSION_LT(3,23,0)
5626 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
5628 ierr = PetscContainerSetCtxDestroy(c,__mfem_array_container_destroy);
5633 ierr = PetscContainerDestroy(&c); CHKERRQ(ierr);
5635 PetscFunctionReturn(PETSC_SUCCESS);
5638static PetscErrorCode MatConvert_hypreParCSR_IS(hypre_ParCSRMatrix* hA,Mat* pA)
5641 ISLocalToGlobalMapping rl2g,cl2g;
5643 hypre_CSRMatrix *hdiag,*hoffd;
5644 MPI_Comm comm = hypre_ParCSRMatrixComm(hA);
5646 const char *names[2] = {
"_mfem_csr_aux",
5650 PetscInt *col_map_offd,*hdi,*hdj,*hoi,*hoj;
5652 PetscInt cum,dr,dc,oc,str,stc,nnz,i,jd,jo;
5653 PetscErrorCode ierr;
5655 PetscFunctionBeginUser;
5657 str = hypre_ParCSRMatrixFirstRowIndex(hA);
5658 stc = hypre_ParCSRMatrixFirstColDiag(hA);
5659 hdiag = hypre_ParCSRMatrixDiag(hA);
5660 hoffd = hypre_ParCSRMatrixOffd(hA);
5661 dr = hypre_CSRMatrixNumRows(hdiag);
5662 dc = hypre_CSRMatrixNumCols(hdiag);
5663 nnz = hypre_CSRMatrixNumNonzeros(hdiag);
5664 hdi = hypre_CSRMatrixI(hdiag);
5665 hdj = hypre_CSRMatrixJ(hdiag);
5666 hdd = hypre_CSRMatrixData(hdiag);
5667 oc = hypre_CSRMatrixNumCols(hoffd);
5668 nnz += hypre_CSRMatrixNumNonzeros(hoffd);
5669 hoi = hypre_CSRMatrixI(hoffd);
5670 hoj = hypre_CSRMatrixJ(hoffd);
5671 hod = hypre_CSRMatrixData(hoffd);
5674 ierr = ISCreateStride(comm,dr,str,1,&is); CHKERRQ(ierr);
5675 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g); CHKERRQ(ierr);
5676 ierr = ISDestroy(&is); CHKERRQ(ierr);
5677 col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
5678 ierr = PetscMalloc1(dc+oc,&aux); CHKERRQ(ierr);
5679 for (i=0; i<dc; i++) { aux[i] = i+stc; }
5680 for (i=0; i<oc; i++) { aux[i+dc] = col_map_offd[i]; }
5681 ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is); CHKERRQ(ierr);
5682 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g); CHKERRQ(ierr);
5683 ierr = ISDestroy(&is); CHKERRQ(ierr);
5686 ierr = MatCreate(comm,pA); CHKERRQ(ierr);
5687 ierr = MatSetSizes(*pA,dr,dc,PETSC_DECIDE,PETSC_DECIDE); CHKERRQ(ierr);
5688 ierr = MatSetType(*pA,MATIS); CHKERRQ(ierr);
5689 ierr = MatSetLocalToGlobalMapping(*pA,rl2g,cl2g); CHKERRQ(ierr);
5690 ierr = ISLocalToGlobalMappingDestroy(&rl2g); CHKERRQ(ierr);
5691 ierr = ISLocalToGlobalMappingDestroy(&cl2g); CHKERRQ(ierr);
5694 ierr = PetscMalloc1(nnz+dr+1,&aux); CHKERRQ(ierr);
5695 ierr = PetscMalloc1(nnz,&data); CHKERRQ(ierr);
5699 *ii = *(hdi++) + *(hoi++);
5700 for (jd=0,jo=0,cum=0; *ii<nnz; cum++)
5704 for (; jd<*hdi; jd++) { *jj++ = *hdj++; *aa++ = *hdd++; }
5705 for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
5706 *(++ii) = *(hdi++) + *(hoi++);
5707 ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold); CHKERRQ(ierr);
5709 for (; cum<dr; cum++) { *(++ii) = nnz; }
5713 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,ii,jj,aa,&lA);
5721 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c); CHKERRQ(ierr);
5722 ierr = PetscContainerSetPointer(c,ptrs[i]); CHKERRQ(ierr);
5723#if PETSC_VERSION_LT(3,23,0)
5724 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
5726 ierr = PetscContainerSetCtxDestroy(c,__mfem_array_container_destroy);
5731 ierr = PetscContainerDestroy(&c); CHKERRQ(ierr);
5733 ierr = MatISSetLocalMat(*pA,lA); CHKERRQ(ierr);
5734 ierr = MatDestroy(&lA); CHKERRQ(ierr);
5735 ierr = MatAssemblyBegin(*pA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5736 ierr = MatAssemblyEnd(*pA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5737 PetscFunctionReturn(PETSC_SUCCESS);
5741#include <petsc/private/matimpl.h>
5743static PetscErrorCode __mfem_MatCreateDummy(MPI_Comm comm,
PetscInt m,
5747 ierr = MatCreate(comm,A); CHKERRQ(ierr);
5748 ierr = MatSetSizes(*A,m,n,PETSC_DECIDE,PETSC_DECIDE); CHKERRQ(ierr);
5749 ierr = PetscObjectChangeTypeName((
PetscObject)*A,
"mfemdummy"); CHKERRQ(ierr);
5750 (*A)->preallocated = PETSC_TRUE;
5751 ierr = MatSetUp(*A); CHKERRQ(ierr);
5752 PetscFunctionReturn(PETSC_SUCCESS);
5755#include <petsc/private/vecimpl.h>
5757#if defined(PETSC_HAVE_DEVICE)
5758static PetscErrorCode __mfem_VecSetOffloadMask(Vec v, PetscOffloadMask m)
5762 PetscFunctionReturn(PETSC_SUCCESS);
5766static PetscErrorCode __mfem_VecBoundToCPU(Vec v, PetscBool *flg)
5769#if defined(PETSC_HAVE_DEVICE)
5770 *flg = v->boundtocpu;
5774 PetscFunctionReturn(PETSC_SUCCESS);
5777static PetscErrorCode __mfem_PetscObjectStateIncrease(
PetscObject o)
5779 PetscErrorCode ierr;
5782 ierr = PetscObjectStateIncrease(o); CHKERRQ(ierr);
5783 PetscFunctionReturn(PETSC_SUCCESS);
void Assign(const T *)
Copy data from a pointer. 'Size()' elements are copied.
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.
A class to handle Block systems in a matrix-free implementation.
int IsZeroBlock(int i, int j) const
Check if block (i,j) is a zero block.
Operator & GetBlock(int i, int j)
Return a reference to block i,j.
int NumRowBlocks() const
Return the number of row blocks.
int NumColBlocks() const
Return the number of column blocks.
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
static int GetId()
Get the device ID of the configured device.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Ordering::Type GetOrdering() const
Return the ordering method.
const FiniteElementCollection * FEColl() const
int GetVDim() const
Returns the vector dimension of the finite element space.
Wrapper for hypre's ParCSR matrix class.
MPI_Comm GetComm() const
MPI communicator.
Wrapper for hypre's parallel vector class.
Identity Operator I: x -> x.
Class used by MFEM to store pointers to host and/or device memory.
bool DeviceIsValid() const
Return true if device pointer is valid.
void CopyFromHost(const T *src, int size)
Copy size entries from the host pointer src to *this.
void MakeAlias(const Memory &base, int offset, int size)
Create a memory object that points inside the memory object base.
bool HostIsValid() const
Return true if host pointer is valid.
bool UseDevice() const
Read the internal device flag.
void CopyToHost(T *dest, int size) const
Copy size entries from *this to the host pointer dest.
bool Empty() const
Return true if the Memory object is empty, see Reset().
void Sync(const Memory &other) const
Copy the host/device pointer validity flags from other to *this.
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.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
TimeDependentOperator * f
Pointer to the associated TimeDependentOperator.
Pointer to an Operator of a specified type.
virtual MemoryClass GetMemoryClass() const
Return the MemoryClass preferred by the Operator.
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 Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Type
Enumeration defining IDs for some classes derived from Operator.
@ ANY_TYPE
ID for the base class Operator, i.e. any type.
@ PETSC_MATIS
ID for class PetscParMatrix, MATIS format.
@ PETSC_MATHYPRE
ID for class PetscParMatrix, MATHYPRE format.
@ PETSC_MATGENERIC
ID for class PetscParMatrix, unspecified format.
@ PETSC_MATAIJ
ID for class PetscParMatrix, MATAIJ format.
@ PETSC_MATNEST
ID for class PetscParMatrix, MATNEST format.
@ PETSC_MATSHELL
ID for class PetscParMatrix, MATSHELL format.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
Abstract parallel finite element space.
HYPRE_BigInt * GetTrueDofOffsets() const
int GetTrueVSize() const override
Return the number of local vector true dofs.
ParMesh * GetParMesh() const
Helper class for handling essential boundary conditions.
PetscBCHandler(Type type_=ZERO)
@ CONSTANT
Constant in time b.c.
void SetTDofs(Array< int > &list)
Sets essential dofs (local, per-process numbering)
virtual void Eval(real_t t, Vector &g)
Boundary conditions evaluation.
void SetTime(real_t t)
Sets the current time.
void SetUp(PetscInt n)
SetUp the helper object, where n is the size of the solution vector.
void ZeroBC(const Vector &x, Vector &y)
y = x on ess_tdof_list_c and y = 0 on ess_tdof_list
Array< int > & GetTDofs()
Gets essential dofs (local, per-process numbering)
void FixResidualBC(const Vector &x, Vector &y)
y = x-g on ess_tdof_list, the rest of y is unchanged
void ApplyBC(const Vector &x, Vector &y)
y = x on ess_tdof_list_c and y = g (internally evaluated) on ess_tdof_list
void Zero(Vector &x)
Replace boundary dofs with 0.
Auxiliary class for BDDC customization.
PetscBDDCSolver(MPI_Comm comm, Operator &op, const PetscBDDCSolverParams &opts=PetscBDDCSolverParams(), const std::string &prefix=std::string())
PetscFieldSplitSolver(MPI_Comm comm, Operator &op, const std::string &prefix=std::string())
PetscH2Solver(Operator &op, ParFiniteElementSpace *fes, const std::string &prefix=std::string())
Abstract class for PETSc's linear solvers.
void SetOperator(const Operator &op) override
operator petsc::KSP() const
Conversion function to PETSc's KSP type.
virtual ~PetscLinearSolver()
void MultTranspose(const Vector &b, Vector &x) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
PetscLinearSolver(MPI_Comm comm, const std::string &prefix=std::string(), bool wrap=true, bool iter_mode=false)
void SetPreconditioner(Solver &precond)
void Mult(const Vector &b, Vector &x) const override
Application of the solver.
bool DeviceRequested() const
void SetHostInvalid() const
void SetHostValid() const
bool WriteRequested() const
const real_t * GetDevicePointer() const
const real_t * GetHostPointer() const
bool IsAliasForSync() const
void MakeAliasForSync(const Memory< real_t > &base_, int offset_, int size_, bool usedev_)
void SetDeviceInvalid() const
bool ReadRequested() const
void SetDeviceValid() const
void Mult(const Vector &b, Vector &x) const override
Application of the solver.
void SetPostCheck(void(*post)(Operator *op, const Vector &X, Vector &Y, Vector &W, bool &changed_y, bool &changed_w))
void SetObjective(void(*obj)(Operator *op, const Vector &x, real_t *f))
Specification of an objective function to be used for line search.
operator petsc::SNES() const
Conversion function to PETSc's SNES type.
virtual ~PetscNonlinearSolver()
void SetJacobianType(Operator::Type type)
void SetUpdate(void(*update)(Operator *op, int it, const Vector &F, const Vector &X, const Vector &D, const Vector &P))
PetscNonlinearSolver(MPI_Comm comm, const std::string &prefix=std::string())
void SetOperator(const Operator &op) override
Specification of the nonlinear operator.
virtual void Init(TimeDependentOperator &f_, enum PetscODESolver::Type type)
Initialize the ODE solver.
virtual void Run(Vector &x, real_t &t, real_t &dt, real_t t_final)
Perform time integration from time t [in] to time tf [in].
virtual void Step(Vector &x, real_t &t, real_t &dt)
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
operator petsc::TS() const
Conversion function to PETSc's TS type.
void SetType(PetscODESolver::Type)
PetscODESolver::Type GetType() const
PetscODESolver(MPI_Comm comm, const std::string &prefix=std::string())
void SetJacobianType(Operator::Type type)
virtual ~PetscODESolver()
PetscPCGSolver(MPI_Comm comm, const std::string &prefix=std::string(), bool iter_mode=false)
Wrapper for PETSc's matrix class.
void Print(const char *fname=NULL, bool binary=false) const
Prints the matrix (to stdout if fname is NULL)
PetscInt GetNumRows() const
Returns the local number of rows.
void ScaleCols(const Vector &s)
Scale the local col i by s(i).
void MakeRef(const PetscParMatrix &master)
Makes this object a reference to another PetscParMatrix.
void EliminateRows(const Array< int > &rows)
Eliminate only the rows from the matrix.
void ConvertOperator(MPI_Comm comm, const Operator &op, petsc::Mat *B, Operator::Type tid)
PetscParMatrix & operator-=(const PetscParMatrix &B)
void Mult(real_t a, const Vector &x, real_t b, Vector &y) const
Matvec: y = a A x + b y.
PetscInt GetColStart() const
Returns the global index of the first local column.
PetscInt M() const
Returns the global number of rows.
void EliminateRowsCols(const Array< int > &rows_cols, const PetscParVector &X, PetscParVector &B, real_t diag=1.)
Eliminate rows and columns from the matrix, and rows from the vector B. Modify B with the BC values i...
PetscParVector * GetY() const
Returns the inner vector in the range of A (it creates it if needed)
MPI_Comm GetComm() const
Get the associated MPI communicator.
PetscParMatrix & operator=(const PetscParMatrix &B)
petsc::Mat ReleaseMat(bool dereference)
Release the PETSc Mat object. If dereference is true, decrement the refcount of the Mat object.
void MakeWrapper(MPI_Comm comm, const Operator *op, petsc::Mat *B)
Creates a wrapper around a mfem::Operator op using PETSc's MATSHELL object and returns the Mat in B.
PetscInt GetNumCols() const
Returns the local number of columns.
PetscInt NNZ() const
Returns the number of nonzeros.
petsc::Mat A
The actual PETSc object.
PetscParVector * GetX() const
Returns the inner vector in the domain of A (it creates it if needed)
void Shift(real_t s)
Shift diagonal by a constant.
PetscParVector * X
Auxiliary vectors for typecasting.
PetscParMatrix()
Create an empty matrix to be used as a reference to an existing matrix.
operator petsc::Mat() const
Typecasting to PETSc's Mat type.
void SetMat(petsc::Mat newA)
Replace the inner Mat Object. The reference count of newA is increased.
void operator*=(real_t s)
Scale all entries by s: A_scaled = s*A.
void SetBlockSize(PetscInt rbs, PetscInt cbs=-1)
Set row and column block sizes of a matrix.
PetscInt N() const
Returns the global number of columns.
PetscParMatrix * Transpose(bool action=false)
Returns the transpose of the PetscParMatrix.
void Init()
Initialize with defaults. Does not initialize inherited members.
void Destroy()
Delete all owned data. Does not perform re-initialization with defaults.
PetscInt GetRowStart() const
Returns the global index of the first local row.
void MultTranspose(real_t a, const Vector &x, real_t b, Vector &y) const
Matvec transpose: y = a A^T x + b y.
PetscParMatrix & operator+=(const PetscParMatrix &B)
void ScaleRows(const Vector &s)
Scale the local row i by s(i).
void ResetMemory()
Completes the operation started with PlaceMemory.
void SetFlagsFromMask_() const
void PlaceMemory(Memory< real_t > &, bool=false)
This requests write access from where the memory is valid and temporarily replaces the corresponding ...
void Randomize(PetscInt seed=0)
Set random values.
void SetBlockSize(PetscInt bs)
Set block size of a vector.
bool UseDevice() const override
Return the device flag of the Memory object used by the Vector.
real_t * HostReadWrite() override
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
void PlaceArray(PetscScalar *temp_data)
Temporarily replace the data of the PETSc Vec object. To return to the original data array,...
PetscInt GlobalSize() const
Returns the global number of rows.
PetscParVector & operator-=(const PetscParVector &y)
real_t * Write(bool=true) override
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void UpdateVecFromFlags()
Update PETSc's Vec after having accessed its data via GetMemory()
void Print(const char *fname=NULL, bool binary=false) const
Prints the vector (to stdout if fname is NULL)
real_t * ReadWrite(bool=true) override
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
const real_t * HostRead() const override
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
const real_t * Read(bool=true) const override
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
real_t * HostWrite() override
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
PetscParVector & operator+=(const PetscParVector &y)
petsc::Vec x
The actual PETSc object.
MPI_Comm GetComm() const
Get the associated MPI communicator.
virtual ~PetscParVector()
Calls PETSc's destroy function.
void ResetArray()
Reset the PETSc Vec object to use its default data. Call this method after the use of PlaceArray().
Vector * GlobalVector() const
Returns the global vector in each processor.
operator petsc::Vec() const
Typecasting to PETSc's Vec type.
PetscParVector & AddValues(const Array< PetscInt > &, const Array< PetscScalar > &)
Add values in a vector.
PetscParVector(MPI_Comm comm, PetscInt glob_size, PetscInt *col=NULL)
Creates vector with given global size and partitioning of the columns.
PetscParVector & SetValues(const Array< PetscInt > &, const Array< PetscScalar > &)
Set values in a vector.
PetscParVector & operator*=(PetscScalar d)
PetscParVector & operator=(PetscScalar d)
Set constant values.
virtual Solver * NewPreconditioner(const OperatorHandle &oh)=0
Abstract class for PETSc's preconditioners.
void Mult(const Vector &b, Vector &x) const override
Application of the preconditioner.
virtual ~PetscPreconditioner()
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
PetscPreconditioner(MPI_Comm comm, const std::string &prefix=std::string())
operator petsc::PC() const
Conversion function to PETSc's PC type.
void MultTranspose(const Vector &b, Vector &x) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Abstract class for monitoring PETSc's solvers.
virtual void MonitorResidual(PetscInt it, PetscReal norm, const Vector &r)
Monitor the residual vector r.
virtual void MonitorSolution(PetscInt it, PetscReal norm, const Vector &x)
Monitor the solution vector x.
virtual void MonitorSolver(PetscSolver *solver)
Generic monitor to take access to the solver.
Abstract class for PETSc's solvers.
PetscClassId cid
The class id of the actual PETSc object.
void SetAbsTol(real_t tol)
void * private_ctx
Private context for solver.
void SetPrintLevel(int plev)
void SetBCHandler(PetscBCHandler *bch)
Sets the object to handle essential boundary conditions.
void SetMaxIter(int max_iter)
void SetRelTol(real_t tol)
void CreatePrivateContext()
virtual ~PetscSolver()
Destroy the PetscParVectors allocated (if any).
MPI_Comm GetComm() const
Get the associated MPI communicator.
PetscSolver()
Construct an empty PetscSolver. Initialize protected objects to NULL.
PetscObject obj
The actual PETSc object (KSP, PC, SNES or TS).
bool clcustom
Boolean to handle SetFromOptions calls.
bool operatorset
Boolean to handle SetOperator calls.
void Customize(bool customize=true) const
Customize object with options set.
void SetMonitor(PetscSolverMonitor *ctx)
Sets user-defined monitoring routine.
void FreePrivateContext()
PetscBCHandler * bchandler
Handler for boundary conditions.
void SetPreconditionerFactory(PetscPreconditionerFactory *factory)
Sets the object for the creation of the preconditioner.
PetscParVector * B
Right-hand side and solution vector.
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
const int * HostReadJ() const
int NumNonZeroElems() const override
Returns the number of the nonzero elements in the matrix.
const real_t * HostReadData() const
void SortColumnIndices()
Sort the column indices corresponding to each row.
const int * HostReadI() const
Base abstract class for first order time dependent operators.
bool isHomogeneous() const
True if type is HOMOGENEOUS.
virtual Operator & GetExplicitGradient(const Vector &u) const
Return an Operator representing dG/du at the given point u and the currently set time.
bool isImplicit() const
True if type is IMPLICIT or HOMOGENEOUS.
virtual void ExplicitMult(const Vector &u, Vector &v) const
Perform the action of the explicit part of the operator, G: v = G(u, t) where t is the current time.
virtual Operator & GetImplicitGradient(const Vector &u, const Vector &k, real_t shift) const
Return an Operator representing (dF/dk shift + dF/du) at the given u, k, and the currently set time.
virtual void SetTime(const real_t t_)
Set the current time.
virtual void ImplicitMult(const Vector &u, const Vector &k, Vector &v) const
Perform the action of the implicit part of the operator, F: v = F(u, k, t) where t is the current tim...
void MakeDataOwner() const
Set the Vector data (host pointer) ownership flag.
Memory< real_t > & GetMemory()
Return a reference to the Memory object used by the Vector.
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void SetSize(int s)
Resize the vector to size s.
void trans(const Vector &u, Vector &x)
real_t f(const Vector &p)
void write(std::ostream &os, T value)
Write 'value' to stream.
T read(std::istream &is)
Read a value from the stream and return it.
MFEM_HOST_DEVICE constexpr auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
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,...
T * HostReadWrite(Memory< T > &mem, int size)
Shortcut to ReadWrite(Memory<T> &mem, int size, false)
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...
PetscParMatrix * TripleMatrixProduct(PetscParMatrix *R, PetscParMatrix *A, PetscParMatrix *P)
Returns the matrix R * A * P.
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device's DeviceMemoryClass,...
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
void MFEMInitializePetsc()
Convenience functions to initialize/finalize PETSc.
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
T * HostWrite(Memory< T > &mem, int size)
Shortcut to Write(const Memory<T> &mem, int size, false)
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
MemoryType
Memory types supported by MFEM.
@ HOST
Host memory; using new[] and delete[].
@ DEVICE
Device memory; using CUDA or HIP *Malloc and *Free.
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....
std::function< real_t(const Vector &)> f(real_t mass_coeff)
struct s_NavierContext ctx
real_t p(const Vector &x, real_t t)
struct _p_PetscObject * PetscObject
MFEM_HOST_DEVICE real_t norm(const Complex &z)
@ HIP_MASK
Biwise-OR of all HIP backends.
@ CUDA_MASK
Biwise-OR of all CUDA backends.