14 #include "../config/config.hpp"
20 #include "../fem/fem.hpp"
23 #if defined(PETSC_HAVE_HYPRE)
24 #include "petscmathypre.h"
28 #if PETSC_VERSION_LT(3,12,0)
29 #define MatComputeOperator(A,B,C) MatComputeExplicitOperator(A,C)
30 #define MatComputeOperatorTranspose(A,B,C) MatComputeExplicitOperatorTranspose(A,C)
54 static PetscErrorCode __mfem_snes_jacobian(
SNES,
Vec,
Mat,
Mat,
void*);
55 static PetscErrorCode __mfem_snes_function(
SNES,
Vec,
Vec,
void*);
58 static PetscErrorCode __mfem_snes_postcheck(SNESLineSearch,
Vec,
Vec,
Vec,
59 PetscBool*,PetscBool*,
void*);
61 static PetscErrorCode __mfem_pc_shell_apply(
PC,
Vec,
Vec);
62 static PetscErrorCode __mfem_pc_shell_apply_transpose(
PC,
Vec,
Vec);
63 static PetscErrorCode __mfem_pc_shell_setup(
PC);
64 static PetscErrorCode __mfem_pc_shell_destroy(
PC);
65 static PetscErrorCode __mfem_pc_shell_view(
PC,PetscViewer);
66 static PetscErrorCode __mfem_mat_shell_apply(
Mat,
Vec,
Vec);
67 static PetscErrorCode __mfem_mat_shell_apply_transpose(
Mat,
Vec,
Vec);
68 static PetscErrorCode __mfem_mat_shell_destroy(
Mat);
69 static PetscErrorCode __mfem_mat_shell_copy(
Mat,
Mat,MatStructure);
70 static PetscErrorCode __mfem_array_container_destroy(
void*);
71 static PetscErrorCode __mfem_matarray_container_destroy(
void*);
72 static PetscErrorCode __mfem_monitor_ctx_destroy(
void**);
75 static PetscErrorCode Convert_Array_IS(MPI_Comm,
bool,
const mfem::Array<int>*,
80 static PetscErrorCode MakeShellPCWithFactory(
PC,
86 #if !defined(PETSC_HAVE_HYPRE)
87 static PetscErrorCode MatConvert_hypreParCSR_AIJ(hypre_ParCSRMatrix*,
Mat*);
88 static PetscErrorCode MatConvert_hypreParCSR_IS(hypre_ParCSRMatrix*,
Mat*);
97 unsigned long int numprec;
98 } __mfem_pc_shell_ctx;
109 void (*postcheck)(
mfem::Operator *op,
const mfem::Vector&, mfem::Vector&,
110 mfem::Vector&,
bool&,
bool&);
114 const mfem::Vector&,
const mfem::Vector&,
115 const mfem::Vector&,
const mfem::Vector&);
127 PetscObjectState cached_ijacstate;
128 PetscObjectState cached_rhsjacstate;
129 PetscObjectState cached_splits_xstate;
130 PetscObjectState cached_splits_xdotstate;
137 } __mfem_monitor_ctx;
140 static PetscErrorCode ierr;
160 ierr = PetscInitialize(argc,argv,rc_file,help);
161 MFEM_VERIFY(!ierr,
"Unable to initialize PETSc");
166 ierr = PetscFinalize();
167 MFEM_VERIFY(!ierr,
"Unable to finalize PETSc");
172 void PetscParVector::_SetDataAndSize_()
177 ierr = VecGetArrayRead(x,&array); PCHKERRQ(x,ierr);
178 ierr = VecGetLocalSize(x,&n); PCHKERRQ(x,ierr);
180 ierr = VecRestoreArrayRead(x,&array); PCHKERRQ(x,ierr);
186 ierr = VecGetSize(x,&N); PCHKERRQ(x,ierr);
190 PetscParVector::PetscParVector(MPI_Comm comm,
const Vector &_x,
193 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
194 ierr = VecSetSizes(
x,_x.
Size(),PETSC_DECIDE); PCHKERRQ(
x,ierr);
195 ierr = VecSetType(
x,VECSTANDARD); PCHKERRQ(
x,ierr);
201 ierr = VecGetArray(
x,&array); PCHKERRQ(
x,ierr);
202 for (
int i = 0; i < _x.
Size(); i++) { array[i] = _x[i]; }
203 ierr = VecRestoreArray(
x,&array); PCHKERRQ(
x,ierr);
210 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
214 MPI_Comm_rank(comm, &myid);
215 ierr = VecSetSizes(
x,col[myid+1]-col[myid],PETSC_DECIDE); PCHKERRQ(
x,ierr);
219 ierr = VecSetSizes(
x,PETSC_DECIDE,glob_size); PCHKERRQ(
x,ierr);
221 ierr = VecSetType(
x,VECSTANDARD); PCHKERRQ(
x,ierr);
228 ierr = VecDestroy(&x); CCHKERRQ(comm,ierr);
234 MFEM_VERIFY(col,
"Missing distribution");
236 MPI_Comm_rank(comm, &myid);
237 ierr = VecCreateMPIWithArray(comm,1,col[myid+1]-col[myid],glob_size,_data,
238 &
x); CCHKERRQ(comm,ierr)
244 ierr = VecDuplicate(y.
x,&
x); PCHKERRQ(
x,ierr);
249 bool transpose,
bool allocate) :
Vector()
254 ierr = VecCreate(comm,&
x);
256 ierr = VecSetSizes(
x,loc,PETSC_DECIDE);
258 ierr = VecSetType(
x,VECSTANDARD);
265 ierr = VecCreateMPIWithArray(comm,1,loc,PETSC_DECIDE,NULL,
266 &
x); CCHKERRQ(comm,ierr);
272 bool transpose,
bool allocate) :
Vector()
277 ierr = MatCreateVecs(pA,&
x,NULL); PCHKERRQ(pA,ierr);
281 ierr = MatCreateVecs(pA,NULL,&
x); PCHKERRQ(pA,ierr);
285 ierr = VecReplaceArray(
x,NULL); PCHKERRQ(
x,ierr);
294 ierr = PetscObjectReference((
PetscObject)y); PCHKERRQ(y,ierr);
304 MPI_Comm comm = pfes->
GetComm();
305 ierr = VecCreate(comm,&
x); CCHKERRQ(comm,ierr);
307 PetscMPIInt myid = 0;
308 if (!HYPRE_AssumedPartitionCheck())
310 MPI_Comm_rank(comm,&myid);
312 ierr = VecSetSizes(
x,offsets[myid+1]-offsets[myid],PETSC_DECIDE);
314 ierr = VecSetType(
x,VECSTANDARD); PCHKERRQ(
x,ierr);
330 ierr = VecScatterCreateToAll(
x,&scctx,&vout); PCHKERRQ(
x,ierr);
331 ierr = VecScatterBegin(scctx,
x,vout,INSERT_VALUES,SCATTER_FORWARD);
333 ierr = VecScatterEnd(scctx,
x,vout,INSERT_VALUES,SCATTER_FORWARD);
335 ierr = VecScatterDestroy(&scctx); PCHKERRQ(
x,ierr);
336 ierr = VecGetArray(vout,&array); PCHKERRQ(
x,ierr);
337 ierr = VecGetLocalSize(vout,&size); PCHKERRQ(
x,ierr);
340 ierr = VecRestoreArray(vout,&array); PCHKERRQ(
x,ierr);
341 ierr = VecDestroy(&vout); PCHKERRQ(
x,ierr);
350 ierr = VecSet(
x,d); PCHKERRQ(
x,ierr);
357 MFEM_VERIFY(idx.
Size() == vals.
Size(),
358 "Size mismatch between indices and values");
362 ierr = VecAssemblyBegin(
x); PCHKERRQ(
x,ierr);
363 ierr = VecAssemblyEnd(
x); PCHKERRQ(
x,ierr);
370 MFEM_VERIFY(idx.
Size() == vals.
Size(),
371 "Size mismatch between indices and values");
375 ierr = VecAssemblyBegin(
x); PCHKERRQ(
x,ierr);
376 ierr = VecAssemblyEnd(
x); PCHKERRQ(
x,ierr);
382 ierr = VecCopy(y.
x,
x); PCHKERRQ(
x,ierr);
388 ierr = VecAXPY(
x,1.0,y.
x); PCHKERRQ(
x,ierr);
394 ierr = VecAXPY(
x,-1.0,y.
x); PCHKERRQ(
x,ierr);
400 ierr = VecScale(
x,s); PCHKERRQ(
x,ierr);
406 ierr = VecShift(
x,s); PCHKERRQ(
x,ierr);
412 ierr = VecPlaceArray(
x,temp_data); PCHKERRQ(
x,ierr);
417 ierr = VecResetArray(
x); PCHKERRQ(
x,ierr);
422 PetscRandom rctx = NULL;
426 ierr = PetscRandomCreate(PetscObjectComm((
PetscObject)
x),&rctx);
428 ierr = PetscRandomSetSeed(rctx,(
unsigned long)seed); PCHKERRQ(x,ierr);
429 ierr = PetscRandomSeed(rctx); PCHKERRQ(x,ierr);
431 ierr = VecSetRandom(
x,rctx); PCHKERRQ(
x,ierr);
432 ierr = PetscRandomDestroy(&rctx); PCHKERRQ(
x,ierr);
443 ierr = PetscViewerBinaryOpen(PetscObjectComm((
PetscObject)
x),fname,
444 FILE_MODE_WRITE,&view);
448 ierr = PetscViewerASCIIOpen(PetscObjectComm((
PetscObject)
x),fname,&view);
451 ierr = VecView(
x,view); PCHKERRQ(
x,ierr);
452 ierr = PetscViewerDestroy(&view); PCHKERRQ(
x,ierr);
456 ierr = VecView(
x,NULL); PCHKERRQ(
x,ierr);
465 ierr = MatGetOwnershipRange(
A,&N,NULL); PCHKERRQ(
A,ierr);
472 ierr = MatGetOwnershipRangeColumn(
A,&N,NULL); PCHKERRQ(
A,ierr);
479 ierr = MatGetLocalSize(
A,&N,NULL); PCHKERRQ(
A,ierr);
486 ierr = MatGetLocalSize(
A,NULL,&N); PCHKERRQ(
A,ierr);
493 ierr = MatGetSize(
A,&N,NULL); PCHKERRQ(
A,ierr);
500 ierr = MatGetSize(
A,NULL,&N); PCHKERRQ(
A,ierr);
507 ierr = MatGetInfo(
A,MAT_GLOBAL_SUM,&info); PCHKERRQ(
A,ierr);
532 rows.
GetData(),PETSC_USE_POINTER,&isr); PCHKERRQ(B,ierr);
534 cols.
GetData(),PETSC_USE_POINTER,&isc); PCHKERRQ(B,ierr);
535 ierr = MatCreateSubMatrix(B,isr,isc,MAT_INITIAL_MATRIX,&
A); PCHKERRQ(B,ierr);
536 ierr = ISDestroy(&isr); PCHKERRQ(B,ierr);
537 ierr = ISDestroy(&isc); PCHKERRQ(B,ierr);
581 BlockDiagonalConstructor(comm,row_starts,row_starts,diag,
594 BlockDiagonalConstructor(comm,row_starts,col_starts,diag,
606 ierr = MatDestroy(&A); CCHKERRQ(comm,ierr);
613 #if defined(PETSC_HAVE_HYPRE)
614 ierr = MatCreateFromParCSR(B,MATAIJ,PETSC_USE_POINTER,&
A);
616 ierr = MatConvert_hypreParCSR_AIJ(B,&
A); CCHKERRQ(B.
GetComm(),ierr);
626 ierr = MatDestroy(&A); CCHKERRQ(comm,ierr);
633 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
641 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
645 MFEM_VERIFY(
height == B.
Height(),
"Invalid number of local rows");
646 MFEM_VERIFY(
width == B.
Width(),
"Invalid number of local columns");
647 ierr = MatAXPY(
A,1.0,B,DIFFERENT_NONZERO_PATTERN); CCHKERRQ(B.
GetComm(),ierr);
656 ierr = MatDuplicate(B,MAT_COPY_VALUES,&
A); CCHKERRQ(B.
GetComm(),ierr);
657 ierr = MatScale(
A,-1.0); PCHKERRQ(
A,ierr);
661 MFEM_VERIFY(
height == B.
Height(),
"Invalid number of local rows");
662 MFEM_VERIFY(
width == B.
Width(),
"Invalid number of local columns");
663 ierr = MatAXPY(
A,-1.0,B,DIFFERENT_NONZERO_PATTERN); CCHKERRQ(B.
GetComm(),ierr);
668 void PetscParMatrix::
669 BlockDiagonalConstructor(MPI_Comm comm,
674 PetscInt lrsize,lcsize,rstart,cstart;
675 PetscMPIInt myid = 0,commsize;
677 ierr = MPI_Comm_size(comm,&commsize); CCHKERRQ(comm,ierr);
678 if (!HYPRE_AssumedPartitionCheck())
680 ierr = MPI_Comm_rank(comm,&myid); CCHKERRQ(comm,ierr);
682 lrsize = row_starts[myid+1]-row_starts[myid];
683 rstart = row_starts[myid];
684 lcsize = col_starts[myid+1]-col_starts[myid];
685 cstart = col_starts[myid];
690 ierr = ISCreateStride(comm,diag->
Height(),rstart,1,&is); CCHKERRQ(comm,ierr);
691 ISLocalToGlobalMapping rl2g,cl2g;
692 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g); PCHKERRQ(is,ierr);
693 ierr = ISDestroy(&is); CCHKERRQ(comm,ierr);
694 if (row_starts != col_starts)
696 ierr = ISCreateStride(comm,diag->
Width(),cstart,1,&is);
698 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g); PCHKERRQ(is,ierr);
699 ierr = ISDestroy(&is); CCHKERRQ(comm,ierr);
703 ierr = PetscObjectReference((
PetscObject)rl2g); PCHKERRQ(rl2g,ierr);
708 ierr = MatCreate(comm,&A); CCHKERRQ(comm,ierr);
709 ierr = MatSetSizes(A,lrsize,lcsize,PETSC_DECIDE,PETSC_DECIDE);
711 ierr = MatSetType(A,MATIS); PCHKERRQ(A,ierr);
712 ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g); PCHKERRQ(A,ierr);
713 ierr = ISLocalToGlobalMappingDestroy(&rl2g); PCHKERRQ(A,ierr)
714 ierr = ISLocalToGlobalMappingDestroy(&cl2g); PCHKERRQ(A,ierr)
718 ierr = MatISGetLocalMat(A,&lA); PCHKERRQ(A,ierr);
719 int *II = diag->GetI();
720 int *JJ = diag->GetJ();
721 #if defined(PETSC_USE_64BIT_INDICES)
724 ierr = PetscMalloc2(m,&pII,nnz,&pJJ); PCHKERRQ(lA,ierr);
725 for (
int i = 0; i < m; i++) { pII[i] = II[i]; }
726 for (
int i = 0; i < nnz; i++) { pJJ[i] = JJ[i]; }
727 ierr = MatSeqAIJSetPreallocationCSR(lA,pII,pJJ,
728 diag->
GetData()); PCHKERRQ(lA,ierr);
729 ierr = PetscFree2(pII,pJJ); PCHKERRQ(lA,ierr);
731 ierr = MatSeqAIJSetPreallocationCSR(lA,II,JJ,
732 diag->
GetData()); PCHKERRQ(lA,ierr);
744 ierr = PetscMalloc1(m,&dii); CCHKERRQ(PETSC_COMM_SELF,ierr);
745 ierr = PetscMalloc1(nnz,&djj); CCHKERRQ(PETSC_COMM_SELF,ierr);
746 ierr = PetscMalloc1(nnz,&da); CCHKERRQ(PETSC_COMM_SELF,ierr);
747 if (
sizeof(
PetscInt) ==
sizeof(
int))
749 ierr = PetscMemcpy(dii,diag->
GetI(),m*
sizeof(
PetscInt));
750 CCHKERRQ(PETSC_COMM_SELF,ierr);
751 ierr = PetscMemcpy(djj,diag->
GetJ(),nnz*
sizeof(
PetscInt));
752 CCHKERRQ(PETSC_COMM_SELF,ierr);
756 int *iii = diag->
GetI();
757 int *jjj = diag->
GetJ();
758 for (
int i = 0; i < m; i++) { dii[i] = iii[i]; }
759 for (
int i = 0; i < nnz; i++) { djj[i] = jjj[i]; }
762 CCHKERRQ(PETSC_COMM_SELF,ierr);
763 ierr = PetscCalloc1(m,&oii);
764 CCHKERRQ(PETSC_COMM_SELF,ierr);
767 ierr = MatCreateMPIAIJWithSplitArrays(comm,lrsize,lcsize,PETSC_DECIDE,
769 dii,djj,da,oii,NULL,NULL,&A);
774 ierr = MatCreateSeqAIJWithArrays(comm,lrsize,lcsize,dii,djj,da,&A);
778 void *ptrs[4] = {dii,djj,da,oii};
779 const char *names[4] = {
"_mfem_csr_dii",
788 ierr = PetscContainerCreate(comm,&c); CCHKERRQ(comm,ierr);
789 ierr = PetscContainerSetPointer(c,ptrs[i]); CCHKERRQ(comm,ierr);
790 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
794 ierr = PetscContainerDestroy(&c); CCHKERRQ(comm,ierr);
799 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); PCHKERRQ(A,ierr);
800 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); PCHKERRQ(A,ierr);
807 return A ? PetscObjectComm((
PetscObject)A) : MPI_COMM_NULL;
820 ierr = MatCreate(comm,A); CCHKERRQ(comm,ierr);
822 PETSC_DECIDE,PETSC_DECIDE); PCHKERRQ(A,ierr);
823 ierr = MatSetType(*A,MATSHELL); PCHKERRQ(A,ierr);
824 ierr = MatShellSetContext(*A,(
void *)op); PCHKERRQ(A,ierr);
825 ierr = MatShellSetOperation(*A,MATOP_MULT,
826 (
void (*)())__mfem_mat_shell_apply);
828 ierr = MatShellSetOperation(*A,MATOP_MULT_TRANSPOSE,
829 (
void (*)())__mfem_mat_shell_apply_transpose);
831 ierr = MatShellSetOperation(*A,MATOP_COPY,
832 (
void (*)())__mfem_mat_shell_copy);
834 ierr = MatShellSetOperation(*A,MATOP_DESTROY,
835 (
void (*)())__mfem_mat_shell_destroy);
837 ierr = MatSetUp(*A); PCHKERRQ(*A,ierr);
862 PetscBool avoidmatconvert = PETSC_FALSE;
865 ierr = PetscObjectTypeCompareAny((
PetscObject)(pA->
A),&avoidmatconvert,MATMFFD,
869 if (pA && !avoidmatconvert)
873 #if PETSC_VERSION_LT(3,10,0)
877 ierr = PetscObjectTypeCompare((
PetscObject)(pA->
A),MATTRANSPOSEMAT,&istrans);
888 #if PETSC_VERSION_LT(3,10,0)
889 ierr = PetscObjectTypeCompare((
PetscObject)(pA->
A),MATIS,&ismatis);
895 ierr = MatTransposeGetMat(pA->
A,&At); CCHKERRQ(pA->
GetComm(),ierr);
896 #if PETSC_VERSION_LT(3,10,0)
897 ierr = PetscObjectTypeCompare((
PetscObject)(At),MATIS,&ismatis);
905 #if PETSC_VERSION_LT(3,10,0)
912 ierr = MatISGetMPIXAIJ(At,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
913 ierr = MatCreateTranspose(B,A); PCHKERRQ(pA->
A,ierr);
914 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
918 ierr = MatISGetMPIXAIJ(pA->
A,MAT_INITIAL_MATRIX,A);
919 PCHKERRQ(pA->
A,ierr);
926 ierr = MPI_Comm_size(comm,&size); CCHKERRQ(comm,ierr);
932 ierr = MatConvert(At,size > 1 ? MATMPIAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);
933 PCHKERRQ(pA->
A,ierr);
934 ierr = MatCreateTranspose(B,A); PCHKERRQ(pA->
A,ierr);
935 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
939 ierr = MatConvert(pA->
A, size > 1 ? MATMPIAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,A);
940 PCHKERRQ(pA->
A,ierr);
949 ierr = MatConvert(At,MATIS,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
950 ierr = MatCreateTranspose(B,A); PCHKERRQ(pA->
A,ierr);
951 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
955 ierr = MatConvert(pA->
A,MATIS,MAT_INITIAL_MATRIX,A); PCHKERRQ(pA->
A,ierr);
960 #if defined(PETSC_HAVE_HYPRE)
964 ierr = MatConvert(At,MATHYPRE,MAT_INITIAL_MATRIX,&B); PCHKERRQ(pA->
A,ierr);
965 ierr = MatCreateTranspose(B,A); PCHKERRQ(pA->
A,ierr);
966 ierr = MatDestroy(&B); PCHKERRQ(pA->
A,ierr);
970 ierr = MatConvert(pA->
A,MATHYPRE,MAT_INITIAL_MATRIX,A); PCHKERRQ(pA->
A,ierr);
973 MFEM_ABORT(
"Reconfigure PETSc with --download-hypre or --with-hypre")
982 MFEM_ABORT(
"Unsupported operator type conversion " << tid)
989 #if defined(PETSC_HAVE_HYPRE)
990 ierr = MatCreateFromParCSR(const_cast<HypreParMatrix&>(*pH),MATAIJ,
991 PETSC_USE_POINTER,A);
993 ierr = MatConvert_hypreParCSR_AIJ(const_cast<HypreParMatrix&>(*pH),A);
999 #if defined(PETSC_HAVE_HYPRE)
1000 ierr = MatCreateFromParCSR(const_cast<HypreParMatrix&>(*pH),MATIS,
1001 PETSC_USE_POINTER,A);
1003 ierr = MatConvert_hypreParCSR_IS(const_cast<HypreParMatrix&>(*pH),A);
1009 #if defined(PETSC_HAVE_HYPRE)
1010 ierr = MatCreateFromParCSR(const_cast<HypreParMatrix&>(*pH),MATHYPRE,
1011 PETSC_USE_POINTER,A);
1014 MFEM_ABORT(
"Reconfigure PETSc with --download-hypre or --with-hypre")
1023 MFEM_ABORT(
"Conversion from HypreParCSR to operator type = " << tid <<
1024 " is not implemented");
1029 Mat *mats,*matsl2l = NULL;
1034 ierr = PetscCalloc1(nr*nc,&mats); CCHKERRQ(PETSC_COMM_SELF,ierr);
1037 ierr = PetscCalloc1(nr,&matsl2l); CCHKERRQ(PETSC_COMM_SELF,ierr);
1039 for (i=0; i<nr; i++)
1041 PetscBool needl2l = PETSC_TRUE;
1043 for (j=0; j<nc; j++)
1051 ierr = PetscObjectQuery((
PetscObject)mats[i*nc+j],
"_MatIS_PtAP_l2l",
1053 PCHKERRQ(mats[i*nc+j],ierr);
1061 ierr = PetscContainerGetPointer(c,(
void**)&l2l);
1063 MFEM_VERIFY(l2l->
Size() == 1,
"Unexpected size "
1064 << l2l->
Size() <<
" for block row " << i );
1065 ierr = PetscObjectReference((
PetscObject)(*l2l)[0]);
1067 matsl2l[i] = (*l2l)[0];
1068 needl2l = PETSC_FALSE;
1074 ierr = MatCreateNest(comm,nr,NULL,nc,NULL,mats,A); CCHKERRQ(comm,ierr);
1077 ierr = MatConvert(*A,MATIS,MAT_INPLACE_MATRIX,A); CCHKERRQ(comm,ierr);
1080 for (
int i=0; i<(int)nr; i++) { (*vmatsl2l)[i] = matsl2l[i]; }
1081 ierr = PetscFree(matsl2l); CCHKERRQ(PETSC_COMM_SELF,ierr);
1084 ierr = PetscContainerCreate(comm,&c); CCHKERRQ(comm,ierr);
1085 ierr = PetscContainerSetPointer(c,vmatsl2l); PCHKERRQ(c,ierr);
1086 ierr = PetscContainerSetUserDestroy(c,__mfem_matarray_container_destroy);
1089 PCHKERRQ((*A),ierr);
1090 ierr = PetscContainerDestroy(&c); CCHKERRQ(comm,ierr);
1092 for (i=0; i<nr*nc; i++) { ierr = MatDestroy(&mats[i]); CCHKERRQ(comm,ierr); }
1093 ierr = PetscFree(mats); CCHKERRQ(PETSC_COMM_SELF,ierr);
1099 ierr = MatCreate(comm,A); CCHKERRQ(comm,ierr);
1100 ierr = MatSetSizes(*A,pI->
Height(),pI->
Width(),PETSC_DECIDE,PETSC_DECIDE);
1102 ierr = MatSetType(*A,MATAIJ); PCHKERRQ(*A,ierr);
1103 ierr = MatMPIAIJSetPreallocation(*A,1,NULL,0,NULL); PCHKERRQ(*A,ierr);
1104 ierr = MatSeqAIJSetPreallocation(*A,1,NULL); PCHKERRQ(*A,ierr);
1105 ierr = MatSetOption(*A,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE); PCHKERRQ(*A,ierr);
1106 ierr = MatGetOwnershipRange(*A,&rst,NULL); PCHKERRQ(*A,ierr);
1109 ierr = MatSetValue(*A,i,i,1.,INSERT_VALUES); PCHKERRQ(*A,ierr);
1111 ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY); PCHKERRQ(*A,ierr);
1112 ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY); PCHKERRQ(*A,ierr);
1128 int n = pS->
Width();
1129 int *ii = pS->
GetI();
1130 int *jj = pS->
GetJ();
1133 ierr = PetscMalloc1(m+1,&pii); CCHKERRQ(PETSC_COMM_SELF,ierr);
1134 ierr = PetscMalloc1(ii[m],&pjj); CCHKERRQ(PETSC_COMM_SELF,ierr);
1135 ierr = PetscMalloc1(ii[m],&pdata); CCHKERRQ(PETSC_COMM_SELF,ierr);
1137 for (
int i = 0; i < m; i++)
1139 bool issorted =
true;
1141 for (
int j = ii[i]; j < ii[i+1]; j++)
1144 if (j != ii[i] && issorted) { issorted = (pjj[j] > pjj[j-1]); }
1149 ierr = PetscSortIntWithScalarArray(pii[i+1]-pii[i],pjj + pii[i],pdata + pii[i]);
1150 CCHKERRQ(PETSC_COMM_SELF,ierr);
1154 ierr = MPI_Comm_size(comm,&size); CCHKERRQ(comm,ierr);
1157 ierr = MatCreateSeqAIJWithArrays(comm,m,n,pii,pjj,pdata,&B);
1158 CCHKERRQ(comm,ierr);
1163 ierr = PetscCalloc1(m+1,&oii); CCHKERRQ(PETSC_COMM_SELF,ierr);
1164 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,
1166 pii,pjj,pdata,oii,NULL,NULL,&B);
1167 CCHKERRQ(comm,ierr);
1169 void *ptrs[4] = {pii,pjj,pdata,oii};
1170 const char *names[4] = {
"_mfem_csr_pii",
1175 for (
int i=0; i<4; i++)
1179 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c); PCHKERRQ(B,ierr);
1180 ierr = PetscContainerSetPointer(c,ptrs[i]); PCHKERRQ(B,ierr);
1181 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
1185 ierr = PetscContainerDestroy(&c); PCHKERRQ(B,ierr);
1193 ierr = MatConvert(B,MATHYPRE,MAT_INITIAL_MATRIX,A); PCHKERRQ(B,ierr);
1194 ierr = MatDestroy(&B); PCHKERRQ(*A,ierr);
1198 ierr = MatConvert(B,MATIS,MAT_INITIAL_MATRIX,A); PCHKERRQ(B,ierr);
1199 ierr = MatDestroy(&B); PCHKERRQ(*A,ierr);
1203 MFEM_ABORT(
"Unsupported operator type conversion " << tid)
1210 "Supported types are ANY_TYPE, PETSC_MATSHELL or PETSC_MATAIJ");
1217 ierr = MatComputeOperator(*A,MATMPIAIJ,&B); CCHKERRQ(comm,ierr);
1218 ierr = PetscObjectTypeCompare((
PetscObject)B,MATMPIAIJ,&isaij);
1219 CCHKERRQ(comm,ierr);
1220 ierr = MatDestroy(A); CCHKERRQ(comm,ierr);
1223 ierr = MatConvert(B,MATAIJ,MAT_INITIAL_MATRIX,A); CCHKERRQ(comm,ierr);
1224 ierr = MatDestroy(&B); CCHKERRQ(comm,ierr);
1238 MPI_Comm comm = MPI_COMM_NULL;
1239 ierr = PetscObjectGetComm((
PetscObject)A,&comm); PCHKERRQ(A,ierr);
1240 ierr = MatDestroy(&A); CCHKERRQ(comm,ierr);
1251 ierr = PetscObjectReference((
PetscObject)a); PCHKERRQ(a,ierr);
1261 if (_A == A) {
return; }
1263 ierr = PetscObjectReference((
PetscObject)_A); PCHKERRQ(_A,ierr);
1278 f = MatMultTranspose;
1279 fadd = MatMultTransposeAdd;
1290 ierr = VecScale(X,a); PCHKERRQ(A,ierr);
1291 ierr = (*fadd)(A,X,Y,Y); PCHKERRQ(A,ierr);
1292 ierr = VecScale(X,1./a); PCHKERRQ(A,ierr);
1296 ierr = VecScale(X,a); PCHKERRQ(A,ierr);
1297 ierr = VecScale(Y,b); PCHKERRQ(A,ierr);
1298 ierr = (*fadd)(A,X,Y,Y); PCHKERRQ(A,ierr);
1299 ierr = VecScale(X,1./a); PCHKERRQ(A,ierr);
1303 ierr = (*f)(A,X,Y); PCHKERRQ(A,ierr);
1306 ierr = VecScale(Y,a); PCHKERRQ(A,ierr);
1318 ierr = VecScale(Y,b); PCHKERRQ(A,ierr);
1322 ierr = VecSet(Y,0.); PCHKERRQ(A,ierr);
1329 ierr = PetscObjectReference((
PetscObject)master.
A); PCHKERRQ(master.
A,ierr);
1341 MFEM_VERIFY(A,
"Mat not present");
1351 MFEM_VERIFY(A,
"Mat not present");
1362 ierr = MatCreateTranspose(A,&B); PCHKERRQ(A,ierr);
1366 ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&B); PCHKERRQ(A,ierr);
1373 ierr = MatScale(A,s); PCHKERRQ(A,ierr);
1378 MFEM_ASSERT(x.
Size() ==
Width(),
"invalid x.Size() = " << x.
Size()
1379 <<
", expected size = " <<
Width());
1380 MFEM_ASSERT(y.
Size() ==
Height(),
"invalid y.Size() = " << y.
Size()
1381 <<
", expected size = " <<
Height());
1387 MatMultKernel(A,a,XX->x,b,YY->
x,
false);
1395 MFEM_ASSERT(x.
Size() ==
Height(),
"invalid x.Size() = " << x.
Size()
1396 <<
", expected size = " <<
Height());
1397 MFEM_ASSERT(y.
Size() ==
Width(),
"invalid y.Size() = " << y.
Size()
1398 <<
", expected size = " <<
Width());
1404 MatMultKernel(A,a,YY->
x,b,XX->x,
true);
1417 ierr = PetscViewerBinaryOpen(PetscObjectComm((
PetscObject)A),fname,
1418 FILE_MODE_WRITE,&view);
1422 ierr = PetscViewerASCIIOpen(PetscObjectComm((
PetscObject)A),fname,&view);
1425 ierr = MatView(A,view); PCHKERRQ(A,ierr);
1426 ierr = PetscViewerDestroy(&view); PCHKERRQ(A,ierr);
1430 ierr = MatView(A,NULL); PCHKERRQ(A,ierr);
1436 MFEM_ASSERT(s.
Size() ==
Height(),
"invalid s.Size() = " << s.
Size()
1437 <<
", expected size = " <<
Height());
1441 ierr = MatDiagonalScale(A,*YY,NULL); PCHKERRQ(A,ierr);
1447 MFEM_ASSERT(s.
Size() ==
Width(),
"invalid s.Size() = " << s.
Size()
1448 <<
", expected size = " <<
Width());
1452 ierr = MatDiagonalScale(A,NULL,*XX); PCHKERRQ(A,ierr);
1458 ierr = MatShift(A,(
PetscScalar)s); PCHKERRQ(A,ierr);
1464 MFEM_ASSERT(s.
Size() ==
Height(),
"invalid s.Size() = " << s.
Size()
1465 <<
", expected size = " <<
Height());
1466 MFEM_ASSERT(s.
Size() ==
Width(),
"invalid s.Size() = " << s.
Size()
1467 <<
", expected size = " <<
Width());
1471 ierr = MatDiagonalSet(A,*XX,ADD_VALUES); PCHKERRQ(A,ierr);
1479 "Petsc TripleMatrixProduct: Number of local cols of A " << A->
Width() <<
1480 " differs from number of local rows of P " << P->
Height());
1482 "Petsc TripleMatrixProduct: Number of local rows of A " << A->
Height() <<
1483 " differs from number of local cols of R " << R->
Width());
1485 ierr = MatMatMatMult(*R,*A,*P,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
1492 Mat pA = *A,pP = *P,pRt = *Rt;
1494 PetscBool Aismatis,Pismatis,Rtismatis;
1497 "Petsc RAP: Number of local cols of A " << A->
Width() <<
1498 " differs from number of local rows of P " << P->
Height());
1500 "Petsc RAP: Number of local rows of A " << A->
Height() <<
1501 " differs from number of local rows of Rt " << Rt->
Height());
1502 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATIS,&Aismatis);
1504 ierr = PetscObjectTypeCompare((
PetscObject)pP,MATIS,&Pismatis);
1506 ierr = PetscObjectTypeCompare((
PetscObject)pRt,MATIS,&Rtismatis);
1513 ISLocalToGlobalMapping cl2gP,cl2gRt;
1514 PetscInt rlsize,clsize,rsize,csize;
1516 ierr = MatGetLocalToGlobalMapping(pP,NULL,&cl2gP); PCHKERRQ(pA,ierr);
1517 ierr = MatGetLocalToGlobalMapping(pRt,NULL,&cl2gRt); PCHKERRQ(pA,ierr);
1518 ierr = MatGetLocalSize(pP,NULL,&clsize); PCHKERRQ(pP,ierr);
1519 ierr = MatGetLocalSize(pRt,NULL,&rlsize); PCHKERRQ(pRt,ierr);
1520 ierr = MatGetSize(pP,NULL,&csize); PCHKERRQ(pP,ierr);
1521 ierr = MatGetSize(pRt,NULL,&rsize); PCHKERRQ(pRt,ierr);
1522 ierr = MatCreate(A->
GetComm(),&B); PCHKERRQ(pA,ierr);
1523 ierr = MatSetSizes(B,rlsize,clsize,rsize,csize); PCHKERRQ(B,ierr);
1524 ierr = MatSetType(B,MATIS); PCHKERRQ(B,ierr);
1525 ierr = MatSetLocalToGlobalMapping(B,cl2gRt,cl2gP); PCHKERRQ(B,ierr);
1526 ierr = MatISGetLocalMat(pA,&lA); PCHKERRQ(pA,ierr);
1527 ierr = MatISGetLocalMat(pP,&lP); PCHKERRQ(pA,ierr);
1528 ierr = MatISGetLocalMat(pRt,&lRt); PCHKERRQ(pA,ierr);
1531 ierr = MatPtAP(lA,lP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&lB);
1537 ierr = MatTranspose(lRt,MAT_INITIAL_MATRIX,&lR); PCHKERRQ(lRt,ierr);
1538 ierr = MatMatMatMult(lR,lA,lP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&lB);
1540 ierr = MatDestroy(&lR); PCHKERRQ(lRt,ierr);
1548 ierr = PetscObjectReference((
PetscObject)lRt); PCHKERRQ(lRt,ierr);
1549 (*vmatsl2l)[0] = lRt;
1552 ierr = PetscContainerCreate(PetscObjectComm((
PetscObject)B),&c);
1554 ierr = PetscContainerSetPointer(c,vmatsl2l); PCHKERRQ(c,ierr);
1555 ierr = PetscContainerSetUserDestroy(c,__mfem_matarray_container_destroy);
1559 ierr = PetscContainerDestroy(&c); PCHKERRQ(B,ierr);
1563 ierr = MatISSetLocalMat(B,lB); PCHKERRQ(lB,ierr);
1564 ierr = MatDestroy(&lB); PCHKERRQ(lA,ierr);
1565 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); PCHKERRQ(B,ierr);
1566 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); PCHKERRQ(B,ierr);
1572 ierr = MatPtAP(pA,pP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
1578 ierr = MatTranspose(pRt,MAT_INITIAL_MATRIX,&pR); PCHKERRQ(Rt,ierr);
1579 ierr = MatMatMatMult(pR,pA,pP,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B);
1581 ierr = MatDestroy(&pR); PCHKERRQ(pRt,ierr);
1596 #if defined(PETSC_HAVE_HYPRE)
1611 ierr = MatMatMult(*A,*B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AB);
1621 ierr = MatDuplicate(A,MAT_COPY_VALUES,&Ae); PCHKERRQ(A,ierr);
1623 ierr = MatAXPY(Ae,-1.,A,SAME_NONZERO_PATTERN); PCHKERRQ(A,ierr);
1632 MFEM_ABORT(
"Missing PetscParMatrix::EliminateRowsCols() with HypreParVectors");
1641 ierr = MatGetSize(A,&M,&N); PCHKERRQ(A,ierr);
1642 MFEM_VERIFY(M == N,
"Rectangular case unsupported");
1645 ierr = MatSetOption(A,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE); PCHKERRQ(A,ierr);
1649 ierr = MatGetOwnershipRange(A,&rst,NULL); PCHKERRQ(A,ierr);
1652 ierr = Convert_Array_IS(
GetComm(),
true,&rows_cols,rst,&dir); PCHKERRQ(A,ierr);
1655 ierr = MatZeroRowsColumnsIS(A,dir,diag,NULL,NULL); PCHKERRQ(A,ierr);
1659 ierr = MatZeroRowsColumnsIS(A,dir,diag,X,B); PCHKERRQ(A,ierr);
1661 ierr = ISDestroy(&dir); PCHKERRQ(A,ierr);
1666 ierr = MatSetOption(A,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE); PCHKERRQ(A,ierr);
1670 ierr = MatGetOwnershipRange(A,&rst,NULL); PCHKERRQ(A,ierr);
1673 ierr = Convert_Array_IS(
GetComm(),
true,&rows,rst,&dir); PCHKERRQ(A,ierr);
1674 ierr = MatZeroRowsIS(A,dir,0.0,NULL,NULL); PCHKERRQ(A,ierr);
1675 ierr = ISDestroy(&dir); PCHKERRQ(A,ierr);
1685 ierr = PetscObjectDereference((
PetscObject)A); CCHKERRQ(comm,ierr);
1694 MFEM_VERIFY(A,
"no associated PETSc Mat object");
1697 ierr = PetscObjectTypeCompare(oA, MATAIJ, &ok); PCHKERRQ(A,ierr);
1699 ierr = PetscObjectTypeCompare(oA, MATSEQAIJ, &ok); PCHKERRQ(A,ierr);
1701 ierr = PetscObjectTypeCompare(oA, MATMPIAIJ, &ok); PCHKERRQ(A,ierr);
1703 ierr = PetscObjectTypeCompare(oA, MATIS, &ok); PCHKERRQ(A,ierr);
1705 ierr = PetscObjectTypeCompare(oA, MATSHELL, &ok); PCHKERRQ(A,ierr);
1707 ierr = PetscObjectTypeCompare(oA, MATNEST, &ok); PCHKERRQ(A,ierr);
1709 #if defined(PETSC_HAVE_HYPRE)
1710 ierr = PetscObjectTypeCompare(oA, MATHYPRE, &ok); PCHKERRQ(A,ierr);
1724 Ae.
Mult(-1.0, X, 1.0, B);
1727 ierr = MatGetDiagonal(pA,diag); PCHKERRQ(pA,ierr);
1728 ierr = VecGetArrayRead(diag,&array); PCHKERRQ(diag,ierr);
1729 for (
int i = 0; i < ess_dof_list.
Size(); i++)
1731 int r = ess_dof_list[i];
1732 B(r) = array[r] * X(r);
1734 ierr = VecRestoreArrayRead(diag,&array); PCHKERRQ(diag,ierr);
1763 if (
cid == KSP_CLASSID)
1766 ierr = KSPSetTolerances(ksp,tol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
1768 else if (
cid == SNES_CLASSID)
1771 ierr = SNESSetTolerances(snes,PETSC_DEFAULT,tol,PETSC_DEFAULT,PETSC_DEFAULT,
1774 else if (
cid == TS_CLASSID)
1777 ierr = TSSetTolerances(ts,PETSC_DECIDE,NULL,tol,NULL);
1781 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
1788 if (
cid == KSP_CLASSID)
1791 ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,tol,PETSC_DEFAULT,PETSC_DEFAULT);
1793 else if (
cid == SNES_CLASSID)
1796 ierr = SNESSetTolerances(snes,tol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
1799 else if (
cid == TS_CLASSID)
1802 ierr = TSSetTolerances(ts,tol,NULL,PETSC_DECIDE,NULL);
1806 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
1813 if (
cid == KSP_CLASSID)
1816 ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
1819 else if (
cid == SNES_CLASSID)
1822 ierr = SNESSetTolerances(snes,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,
1823 max_iter,PETSC_DEFAULT);
1825 else if (
cid == TS_CLASSID)
1828 ierr = TSSetMaxSteps(ts,max_iter);
1832 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
1840 typedef PetscErrorCode (*myPetscFunc)(
void**);
1841 PetscViewerAndFormat *vf = NULL;
1842 PetscViewer viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm(
obj));
1846 ierr = PetscViewerAndFormatCreate(viewer,PETSC_VIEWER_DEFAULT,&vf);
1849 if (
cid == KSP_CLASSID)
1857 ierr = KSPMonitorCancel(ksp); PCHKERRQ(ksp,ierr);
1861 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorDefault,vf,
1862 (myPetscFunc)PetscViewerAndFormatDestroy);
1867 ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE); PCHKERRQ(ksp,ierr);
1868 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorSingularValue,vf,
1869 (myPetscFunc)PetscViewerAndFormatDestroy);
1873 ierr = PetscViewerAndFormatCreate(viewer,PETSC_VIEWER_DEFAULT,&vf);
1874 PCHKERRQ(viewer,ierr);
1875 ierr = KSPMonitorSet(ksp,(myMonitor)KSPMonitorTrueResidualNorm,vf,
1876 (myPetscFunc)PetscViewerAndFormatDestroy);
1881 else if (
cid == SNES_CLASSID)
1887 ierr = SNESMonitorCancel(snes); PCHKERRQ(snes,ierr);
1891 ierr = SNESMonitorSet(snes,(myMonitor)SNESMonitorDefault,vf,
1892 (myPetscFunc)PetscViewerAndFormatDestroy);
1893 PCHKERRQ(snes,ierr);
1896 else if (
cid == TS_CLASSID)
1901 ierr = TSMonitorCancel(ts); PCHKERRQ(ts,ierr);
1906 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
1912 return obj ? PetscObjectComm(
obj) : MPI_COMM_NULL;
1917 __mfem_monitor_ctx *monctx;
1918 ierr = PetscNew(&monctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
1919 monctx->solver =
this;
1920 monctx->monitor =
ctx;
1921 if (
cid == KSP_CLASSID)
1923 ierr = KSPMonitorSet((
KSP)
obj,__mfem_ksp_monitor,monctx,
1924 __mfem_monitor_ctx_destroy);
1927 else if (
cid == SNES_CLASSID)
1929 ierr = SNESMonitorSet((
SNES)
obj,__mfem_snes_monitor,monctx,
1930 __mfem_monitor_ctx_destroy);
1933 else if (
cid == TS_CLASSID)
1935 ierr = TSMonitorSet((
TS)
obj,__mfem_ts_monitor,monctx,
1936 __mfem_monitor_ctx_destroy);
1941 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
1948 if (
cid == SNES_CLASSID)
1950 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)
private_ctx;
1953 else if (
cid == TS_CLASSID)
1955 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)
private_ctx;
1960 MFEM_ABORT(
"Handling of essential bc only implemented for nonlinear and time-dependent solvers");
1967 if (
cid == TS_CLASSID)
1972 ierr = TSGetSNES((
TS)
obj,&snes); PCHKERRQ(obj,ierr);
1973 ierr = SNESGetKSP(snes,&ksp); PCHKERRQ(obj,ierr);
1974 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(obj,ierr);
1976 else if (
cid == SNES_CLASSID)
1980 ierr = SNESGetKSP((
SNES)
obj,&ksp); PCHKERRQ(obj,ierr);
1981 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(obj,ierr);
1983 else if (
cid == KSP_CLASSID)
1985 ierr = KSPGetPC((
KSP)
obj,&pc); PCHKERRQ(obj,ierr);
1987 else if (
cid == PC_CLASSID)
1993 MFEM_ABORT(
"No support for PetscPreconditionerFactory for this object");
1997 ierr = MakeShellPCWithFactory(pc,factory); PCHKERRQ(pc,ierr);
2001 ierr = PCSetType(pc, PCNONE); PCHKERRQ(pc,ierr);
2007 if (!customize) {
clcustom =
true; }
2010 if (
cid == PC_CLASSID)
2013 ierr = PCSetFromOptions(pc); PCHKERRQ(pc, ierr);
2015 else if (
cid == KSP_CLASSID)
2018 ierr = KSPSetFromOptions(ksp); PCHKERRQ(ksp, ierr);
2020 else if (
cid == SNES_CLASSID)
2023 ierr = SNESSetFromOptions(snes); PCHKERRQ(snes, ierr);
2025 else if (
cid == TS_CLASSID)
2028 ierr = TSSetFromOptions(ts); PCHKERRQ(ts, ierr);
2032 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2040 if (
cid == KSP_CLASSID)
2043 KSPConvergedReason reason;
2044 ierr = KSPGetConvergedReason(ksp,&reason);
2046 return reason > 0 ? 1 : 0;
2048 else if (
cid == SNES_CLASSID)
2051 SNESConvergedReason reason;
2052 ierr = SNESGetConvergedReason(snes,&reason);
2053 PCHKERRQ(snes,ierr);
2054 return reason > 0 ? 1 : 0;
2056 else if (
cid == TS_CLASSID)
2059 TSConvergedReason reason;
2060 ierr = TSGetConvergedReason(ts,&reason);
2062 return reason > 0 ? 1 : 0;
2066 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2073 if (
cid == KSP_CLASSID)
2077 ierr = KSPGetIterationNumber(ksp,&its);
2081 else if (
cid == SNES_CLASSID)
2085 ierr = SNESGetIterationNumber(snes,&its);
2086 PCHKERRQ(snes,ierr);
2089 else if (
cid == TS_CLASSID)
2093 ierr = TSGetStepNumber(ts,&its);
2099 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2106 if (
cid == KSP_CLASSID)
2110 ierr = KSPGetResidualNorm(ksp,&norm);
2114 if (
cid == SNES_CLASSID)
2118 ierr = SNESGetFunctionNorm(snes,&norm);
2119 PCHKERRQ(snes,ierr);
2124 MFEM_ABORT(
"CLASSID = " <<
cid <<
" is not implemented!");
2125 return PETSC_MAX_REAL;
2132 if (
cid == SNES_CLASSID)
2134 __mfem_snes_ctx *snes_ctx;
2135 ierr = PetscNew(&snes_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2136 snes_ctx->op = NULL;
2137 snes_ctx->bchandler = NULL;
2138 snes_ctx->work = NULL;
2142 else if (
cid == TS_CLASSID)
2144 __mfem_ts_ctx *ts_ctx;
2145 ierr = PetscNew(&ts_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2147 ts_ctx->bchandler = NULL;
2148 ts_ctx->work = NULL;
2149 ts_ctx->work2 = NULL;
2150 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
2151 ts_ctx->cached_ijacstate = -1;
2152 ts_ctx->cached_rhsjacstate = -1;
2153 ts_ctx->cached_splits_xstate = -1;
2154 ts_ctx->cached_splits_xdotstate = -1;
2165 if (
cid == SNES_CLASSID)
2167 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx *)
private_ctx;
2168 delete snes_ctx->work;
2170 else if (
cid == TS_CLASSID)
2172 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx *)
private_ctx;
2173 delete ts_ctx->work;
2174 delete ts_ctx->work2;
2176 ierr = PetscFree(
private_ctx); CCHKERRQ(PETSC_COMM_SELF,ierr);
2183 : bctype(_type), setup(false), eval_t(0.0),
2184 eval_t_cached(std::numeric_limits<double>::min())
2192 ess_tdof_list.
Assign(list);
2198 if (setup) {
return; }
2202 this->
Eval(eval_t,eval_g);
2203 eval_t_cached = eval_t;
2214 (*this).SetUp(x.
Size());
2218 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2220 y[ess_tdof_list[i]] = 0.0;
2225 if (bctype !=
CONSTANT && eval_t != eval_t_cached)
2227 Eval(eval_t,eval_g);
2228 eval_t_cached = eval_t;
2230 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2232 y[ess_tdof_list[i]] = eval_g[ess_tdof_list[i]];
2239 (*this).SetUp(x.
Size());
2242 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2244 x[ess_tdof_list[i]] = 0.0;
2249 if (bctype !=
CONSTANT && eval_t != eval_t_cached)
2251 Eval(eval_t,eval_g);
2252 eval_t_cached = eval_t;
2254 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2256 x[ess_tdof_list[i]] = eval_g[ess_tdof_list[i]];
2263 (*this).SetUp(x.
Size());
2266 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2268 y[ess_tdof_list[i]] = x[ess_tdof_list[i]];
2273 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2275 y[ess_tdof_list[i]] = x[ess_tdof_list[i]] - eval_g[ess_tdof_list[i]];
2282 (*this).SetUp(x.
Size());
2283 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2285 x[ess_tdof_list[i]] = 0.0;
2291 (*this).SetUp(x.
Size());
2293 for (
int i = 0; i < ess_tdof_list.
Size(); ++i)
2295 y[ess_tdof_list[i]] = 0.0;
2306 ierr = KSPCreate(comm,&ksp); CCHKERRQ(comm,ierr);
2308 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
2309 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2313 const std::string &prefix)
2319 ierr = PetscObjectGetClassId(obj,&
cid); PCHKERRQ(obj,ierr);
2320 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2325 const std::string &prefix)
2331 ierr = PetscObjectGetClassId(obj, &
cid); PCHKERRQ(obj, ierr);
2332 ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
2344 bool delete_pA =
false;
2362 MFEM_VERIFY(pA,
"Unsupported operation!");
2370 PetscInt nheight,nwidth,oheight,owidth;
2372 ierr = KSPGetOperators(ksp,&C,NULL); PCHKERRQ(ksp,ierr);
2373 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
2374 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
2375 if (nheight != oheight || nwidth != owidth)
2379 ierr = KSPReset(ksp); PCHKERRQ(ksp,ierr);
2386 ierr = KSPSetOperators(ksp,A,A); PCHKERRQ(ksp,ierr);
2395 if (delete_pA) {
delete pA; }
2410 bool delete_pA =
false;
2428 MFEM_VERIFY(pA,
"Unsupported operation!");
2431 bool delete_ppA =
false;
2434 if (oA == poA && !wrap)
2444 MFEM_VERIFY(ppA,
"Unsupported operation!");
2453 PetscInt nheight,nwidth,oheight,owidth;
2455 ierr = KSPGetOperators(ksp,&C,NULL); PCHKERRQ(ksp,ierr);
2456 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
2457 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
2458 if (nheight != oheight || nwidth != owidth)
2462 ierr = KSPReset(ksp); PCHKERRQ(ksp,ierr);
2469 ierr = KSPSetOperators(ksp,A,P); PCHKERRQ(ksp,ierr);
2478 if (delete_pA) {
delete pA; }
2479 if (delete_ppA) {
delete ppA; }
2489 ierr = KSPGetOperatorsSet(ksp,&amat,NULL); PCHKERRQ(ksp,ierr);
2492 ierr = KSPGetOperators(ksp,&A,NULL); PCHKERRQ(ksp,ierr);
2493 ierr = PetscObjectReference((
PetscObject)A); PCHKERRQ(ksp,ierr);
2498 ierr = KSPSetPC(ksp,*ppc); PCHKERRQ(ksp,ierr);
2507 ierr = KSPGetPC(ksp,&pc); PCHKERRQ(ksp,ierr);
2508 ierr = MakeShellPC(pc,precond,
false); PCHKERRQ(ksp,ierr);
2514 ierr = KSPGetOperators(ksp,NULL,&P); PCHKERRQ(ksp,ierr);
2515 ierr = PetscObjectReference((
PetscObject)P); PCHKERRQ(ksp,ierr);
2516 ierr = KSPSetOperators(ksp,A,P); PCHKERRQ(ksp,ierr);
2517 ierr = MatDestroy(&A); PCHKERRQ(ksp,ierr);
2518 ierr = MatDestroy(&P); PCHKERRQ(ksp,ierr);
2522 void PetscLinearSolver::MultKernel(
const Vector &b,
Vector &x,
bool trans)
const
2529 ierr = KSPGetOperators(ksp, &pA, NULL); PCHKERRQ(
obj, ierr);
2537 PetscParMatrix A = PetscParMatrix(pA,
true);
2538 X =
new PetscParVector(A,
false,
false);
2546 ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)
iterative_mode);
2547 PCHKERRQ(ksp, ierr);
2552 ierr = KSPSolveTranspose(ksp,
B->
x, X->x); PCHKERRQ(ksp,ierr);
2556 ierr = KSPSolve(ksp,
B->
x, X->x); PCHKERRQ(ksp,ierr);
2564 (*this).MultKernel(b,x,
false);
2569 (*this).MultKernel(b,x,
true);
2576 ierr = PetscObjectGetComm((
PetscObject)ksp,&comm); PCHKERRQ(ksp,ierr);
2577 ierr = KSPDestroy(&ksp); CCHKERRQ(comm,ierr);
2586 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
2588 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
2595 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
2597 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
2601 const std::string &prefix)
2605 ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
2607 ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
2613 const std::string &prefix)
2617 ierr = PCCreate(comm,&pc); CCHKERRQ(comm,ierr);
2619 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
2620 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
2624 const string &prefix)
2630 ierr = PetscObjectGetClassId(obj,&
cid); PCHKERRQ(obj,ierr);
2631 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
2636 const string &prefix)
2640 ierr = PCCreate(comm,&pc); CCHKERRQ(comm,ierr);
2642 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
2643 ierr = PCSetOptionsPrefix(pc, prefix.c_str()); PCHKERRQ(pc, ierr);
2649 bool delete_pA =
false;
2666 PetscInt nheight,nwidth,oheight,owidth;
2668 ierr = PCGetOperators(pc,&C,NULL); PCHKERRQ(pc,ierr);
2669 ierr = MatGetSize(A,&nheight,&nwidth); PCHKERRQ(A,ierr);
2670 ierr = MatGetSize(C,&oheight,&owidth); PCHKERRQ(A,ierr);
2671 if (nheight != oheight || nwidth != owidth)
2675 ierr = PCReset(pc); PCHKERRQ(pc,ierr);
2681 ierr = PCSetOperators(pc,pA->
A,pA->
A); PCHKERRQ(
obj,ierr);
2690 if (delete_pA) {
delete pA; };
2693 void PetscPreconditioner::MultKernel(
const Vector &b,
Vector &x,
2701 ierr = PCGetOperators(pc, NULL, &pA); PCHKERRQ(
obj, ierr);
2709 PetscParMatrix A(pA,
true);
2710 X =
new PetscParVector(A,
false,
false);
2721 ierr = PCApplyTranspose(pc,
B->
x, X->x); PCHKERRQ(pc, ierr);
2725 ierr = PCApply(pc,
B->
x, X->x); PCHKERRQ(pc, ierr);
2733 (*this).MultKernel(b,x,
false);
2738 (*this).MultKernel(b,x,
true);
2745 ierr = PetscObjectGetComm((
PetscObject)pc,&comm); PCHKERRQ(pc,ierr);
2746 ierr = PCDestroy(&pc); CCHKERRQ(comm,ierr);
2754 for (
int i = 0; i < x.
Size(); i++) { y(i) = x(i); }
2757 void PetscBDDCSolver::BDDCSolverConstructor(
const PetscBDDCSolverParams &opts)
2759 MPI_Comm comm = PetscObjectComm(
obj);
2764 ierr = PCGetOperators(pc,NULL,&pA); PCHKERRQ(pc,ierr);
2768 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATIS,&ismatis);
2770 MFEM_VERIFY(ismatis,
"PetscBDDCSolver needs the matrix in unassembled format");
2773 ParFiniteElementSpace *fespace = opts.fespace;
2774 if (opts.netflux && !fespace)
2776 MFEM_WARNING(
"Don't know how to compute an auxiliary quadrature form without a ParFiniteElementSpace");
2783 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(comm,ierr);
2784 ierr = MatNullSpaceCreate(PetscObjectComm((
PetscObject)lA),PETSC_TRUE,0,NULL,
2785 &nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
2786 ierr = MatSetNearNullSpace(lA,nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
2787 ierr = MatNullSpaceDestroy(&nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
2791 ierr = PCSetType(pc,PCBDDC); PCHKERRQ(
obj,ierr);
2794 ierr = MatGetOwnershipRange(pA,&rst,NULL); PCHKERRQ(pA,ierr);
2795 ierr = MatGetLocalSize(pA,&nl,NULL); PCHKERRQ(pA,ierr);
2804 int vdim = fespace->GetVDim();
2811 ierr = MatSetBlockSize(pA,vdim); PCHKERRQ(pA,ierr);
2812 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(PETSC_COMM_SELF,ierr);
2813 ierr = MatSetBlockSize(lA,vdim); PCHKERRQ(pA,ierr);
2822 ierr = PetscMalloc1(nf,&fields); CCHKERRQ(PETSC_COMM_SELF,ierr);
2835 ierr = ISCreateStride(comm,nlf,st,bs,&fields[i]); CCHKERRQ(comm,ierr);
2841 const FiniteElementCollection *fec = fespace->FEColl();
2842 bool h1space =
dynamic_cast<const H1_FECollection*
>(fec);
2845 ParFiniteElementSpace *fespace_coords = fespace;
2847 sdim = fespace->GetParMesh()->SpaceDimension();
2850 fespace_coords =
new ParFiniteElementSpace(fespace->GetParMesh(),fec,sdim,
2853 VectorFunctionCoefficient coeff_coords(sdim, func_coords);
2854 ParGridFunction gf_coords(fespace_coords);
2855 gf_coords.ProjectCoefficient(coeff_coords);
2856 HypreParVector *hvec_coords = gf_coords.ParallelProject();
2863 Vec pvec_coords,lvec_coords;
2864 ISLocalToGlobalMapping l2g;
2870 ierr = VecCreateMPIWithArray(comm,sdim,hvec_coords->Size(),
2871 hvec_coords->GlobalSize(),hvec_coords->GetData(),&pvec_coords);
2872 CCHKERRQ(comm,ierr);
2873 ierr = MatISGetLocalMat(pA,&lA); CCHKERRQ(PETSC_COMM_SELF,ierr);
2874 ierr = MatCreateVecs(lA,&lvec_coords,NULL); CCHKERRQ(PETSC_COMM_SELF,ierr);
2875 ierr = VecSetBlockSize(lvec_coords,sdim); CCHKERRQ(PETSC_COMM_SELF,ierr);
2876 ierr = MatGetLocalToGlobalMapping(pA,&l2g,NULL); CCHKERRQ(comm,ierr);
2877 ierr = MatGetLayouts(pA,&rmap,NULL); CCHKERRQ(comm,ierr);
2878 ierr = PetscSFCreate(comm,&sf); CCHKERRQ(comm,ierr);
2879 ierr = ISLocalToGlobalMappingGetIndices(l2g,&gidxs); CCHKERRQ(comm,ierr);
2880 ierr = ISLocalToGlobalMappingGetSize(l2g,&nleaves); CCHKERRQ(comm,ierr);
2881 ierr = PetscSFSetGraphLayout(sf,rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);
2882 CCHKERRQ(comm,ierr);
2883 ierr = ISLocalToGlobalMappingRestoreIndices(l2g,&gidxs); CCHKERRQ(comm,ierr);
2888 ierr = VecGetArrayRead(pvec_coords,&garray); CCHKERRQ(PETSC_COMM_SELF,ierr);
2889 ierr = VecGetArray(lvec_coords,&larray); CCHKERRQ(PETSC_COMM_SELF,ierr);
2890 ierr = PetscSFBcastBegin(sf,MPIU_SCALAR,garray,larray); CCHKERRQ(comm,ierr);
2891 ierr = PetscSFBcastEnd(sf,MPIU_SCALAR,garray,larray); CCHKERRQ(comm,ierr);
2892 ierr = VecRestoreArrayRead(pvec_coords,&garray); CCHKERRQ(PETSC_COMM_SELF,ierr);
2893 ierr = VecRestoreArray(lvec_coords,&larray); CCHKERRQ(PETSC_COMM_SELF,ierr);
2895 ierr = VecDestroy(&pvec_coords); CCHKERRQ(comm,ierr);
2896 ierr = MatNullSpaceCreateRigidBody(lvec_coords,&nnsp);
2897 CCHKERRQ(PETSC_COMM_SELF,ierr);
2898 ierr = VecDestroy(&lvec_coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
2899 ierr = MatSetNearNullSpace(lA,nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
2900 ierr = MatNullSpaceDestroy(&nnsp); CCHKERRQ(PETSC_COMM_SELF,ierr);
2901 ierr = PetscSFDestroy(&sf); CCHKERRQ(PETSC_COMM_SELF,ierr);
2905 ierr = PetscMalloc1(nl*sdim,&coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
2915 ierr = ISGetLocalSize(fields[i],&nn); CCHKERRQ(comm,ierr);
2916 ierr = ISGetIndices(fields[i],&idxs); CCHKERRQ(comm,ierr);
2920 for (
PetscInt d = 0; d < sdim; d++)
2922 coords[sdim*idx+d] = data[sdim*j+d];
2925 ierr = ISRestoreIndices(fields[i],&idxs); CCHKERRQ(comm,ierr);
2930 ierr = PetscMemcpy(coords,hvec_coords->GetData(),nl*sdim*
sizeof(
PetscReal));
2931 CCHKERRQ(comm,ierr);
2933 if (fespace_coords != fespace)
2935 delete fespace_coords;
2942 IS dir = NULL, neu = NULL;
2945 Array<Mat> *l2l = NULL;
2946 if (opts.ess_dof_local || opts.nat_dof_local)
2951 MFEM_VERIFY(c,
"Local-to-local PETSc container not present");
2952 ierr = PetscContainerGetPointer(c,(
void**)&l2l); PCHKERRQ(c,ierr);
2959 PetscBool lpr = PETSC_FALSE,pr;
2960 if (opts.ess_dof) { lpr = PETSC_TRUE; }
2961 ierr = MPI_Allreduce(&lpr,&pr,1,MPIU_BOOL,MPI_LOR,comm);
2963 MFEM_VERIFY(lpr == pr,
"ess_dof should be collectively set");
2965 if (opts.nat_dof) { lpr = PETSC_TRUE; }
2966 ierr = MPI_Allreduce(&lpr,&pr,1,MPIU_BOOL,MPI_LOR,comm);
2968 MFEM_VERIFY(lpr == pr,
"nat_dof should be collectively set");
2971 ms[0] = -nf; ms[1] = nf;
2972 ierr = MPI_Allreduce(&ms,&Ms,2,MPIU_INT,MPI_MAX,comm);
2974 MFEM_VERIFY(-Ms[0] == Ms[1],
2975 "number of fields should be the same across processes");
2982 PetscInt st = opts.ess_dof_local ? 0 : rst;
2983 if (!opts.ess_dof_local)
2986 ierr = Convert_Array_IS(comm,
true,opts.ess_dof,st,&dir);
2987 CCHKERRQ(comm,ierr);
2988 ierr = PCBDDCSetDirichletBoundaries(pc,dir); PCHKERRQ(pc,ierr);
2993 ierr = Convert_Vmarks_IS(comm,*l2l,opts.ess_dof,st,&dir);
2994 CCHKERRQ(comm,ierr);
2995 ierr = PCBDDCSetDirichletBoundariesLocal(pc,dir); PCHKERRQ(pc,ierr);
3000 PetscInt st = opts.nat_dof_local ? 0 : rst;
3001 if (!opts.nat_dof_local)
3004 ierr = Convert_Array_IS(comm,
true,opts.nat_dof,st,&neu);
3005 CCHKERRQ(comm,ierr);
3006 ierr = PCBDDCSetNeumannBoundaries(pc,neu); PCHKERRQ(pc,ierr);
3011 ierr = Convert_Vmarks_IS(comm,*l2l,opts.nat_dof,st,&neu);
3012 CCHKERRQ(comm,ierr);
3013 ierr = PCBDDCSetNeumannBoundariesLocal(pc,neu); PCHKERRQ(pc,ierr);
3020 ierr = PCBDDCSetDofsSplitting(pc,nf,fields); PCHKERRQ(pc,ierr);
3024 ierr = ISDestroy(&fields[i]); CCHKERRQ(comm,ierr);
3026 ierr = PetscFree(fields); CCHKERRQ(PETSC_COMM_SELF,ierr);
3031 ierr = PCSetCoordinates(pc,sdim,nl,coords); PCHKERRQ(pc,ierr);
3033 ierr = PetscFree(coords); CCHKERRQ(PETSC_COMM_SELF,ierr);
3042 const FiniteElementCollection *fec = fespace->FEColl();
3043 bool edgespace, rtspace, h1space;
3044 bool needint = opts.netflux;
3045 bool tracespace, rt_tracespace, edge_tracespace;
3047 PetscBool B_is_Trans = PETSC_FALSE;
3049 ParMesh *pmesh = (ParMesh *) fespace->GetMesh();
3050 dim = pmesh->Dimension();
3051 vdim = fespace->GetVDim();
3052 h1space =
dynamic_cast<const H1_FECollection*
>(fec);
3053 rtspace =
dynamic_cast<const RT_FECollection*
>(fec);
3054 edgespace =
dynamic_cast<const ND_FECollection*
>(fec);
3055 edge_tracespace =
dynamic_cast<const ND_Trace_FECollection*
>(fec);
3056 rt_tracespace =
dynamic_cast<const RT_Trace_FECollection*
>(fec);
3057 tracespace = edge_tracespace || rt_tracespace;
3060 if (fespace->GetNE() > 0)
3064 p = fespace->GetOrder(0);
3068 p = fespace->GetFaceOrder(0);
3069 if (dim == 2) { p++; }
3080 MFEM_WARNING(
"Tracespace case doesn't work for H(curl) and p=2,"
3081 " not using auxiliary quadrature");
3087 FiniteElementCollection *vfec;
3090 vfec =
new H1_Trace_FECollection(p,dim);
3094 vfec =
new H1_FECollection(p,dim);
3096 ParFiniteElementSpace *vfespace =
new ParFiniteElementSpace(pmesh,vfec);
3097 ParDiscreteLinearOperator *grad;
3098 grad =
new ParDiscreteLinearOperator(vfespace,fespace);
3101 grad->AddTraceFaceInterpolator(
new GradientInterpolator);
3105 grad->AddDomainInterpolator(
new GradientInterpolator);
3109 HypreParMatrix *hG = grad->ParallelAssemble();
3110 PetscParMatrix *G =
new PetscParMatrix(hG,
PETSC_MATAIJ);
3114 PetscBool conforming = PETSC_TRUE;
3115 if (pmesh->Nonconforming()) { conforming = PETSC_FALSE; }
3116 ierr = PCBDDCSetDiscreteGradient(pc,*G,p,0,PETSC_TRUE,conforming);
3128 MFEM_WARNING(
"Tracespace case doesn't work for H(div), not using"
3129 " auxiliary quadrature");
3135 if (vdim != dim) { needint =
false; }
3138 PetscParMatrix *
B = NULL;
3144 FiniteElementCollection *auxcoll;
3145 if (tracespace) { auxcoll =
new RT_Trace_FECollection(p,dim); }
3150 auxcoll =
new H1_FECollection(std::max(p-1,1),dim);
3154 auxcoll =
new L2_FECollection(p,dim);
3157 ParFiniteElementSpace *pspace =
new ParFiniteElementSpace(pmesh,auxcoll);
3158 ParMixedBilinearForm *b =
new ParMixedBilinearForm(fespace,pspace);
3164 b->AddTraceFaceIntegrator(
new VectorFECurlIntegrator);
3168 b->AddDomainIntegrator(
new VectorFECurlIntegrator);
3175 b->AddTraceFaceIntegrator(
new VectorFEDivergenceIntegrator);
3179 b->AddDomainIntegrator(
new VectorFEDivergenceIntegrator);
3184 b->AddDomainIntegrator(
new VectorDivergenceIntegrator);
3189 b->ParallelAssemble(Bh);
3191 Bh.SetOperatorOwner(
false);
3196 ierr = MatTranspose(pB,MAT_INPLACE_MATRIX,&pB); PCHKERRQ(pA,ierr);
3197 if (!opts.ess_dof_local)
3199 ierr = MatZeroRowsIS(pB,dir,0.,NULL,NULL); PCHKERRQ(pA,ierr);
3203 ierr = MatZeroRowsLocalIS(pB,dir,0.,NULL,NULL); PCHKERRQ(pA,ierr);
3205 B_is_Trans = PETSC_TRUE;
3214 ierr = PCBDDCSetDivergenceMat(pc,*B,B_is_Trans,NULL); PCHKERRQ(pc,ierr);
3218 ierr = ISDestroy(&dir); PCHKERRQ(pc,ierr);
3219 ierr = ISDestroy(&neu); PCHKERRQ(pc,ierr);
3224 const std::string &prefix)
3227 BDDCSolverConstructor(opts);
3233 const std::string &prefix)
3236 BDDCSolverConstructor(opts);
3241 const string &prefix)
3245 ierr = PCSetType(pc,PCFIELDSPLIT); PCHKERRQ(pc,ierr);
3248 ierr = PCGetOperators(pc,&pA,NULL); PCHKERRQ(pc,ierr);
3252 ierr = PetscObjectTypeCompare((
PetscObject)pA,MATNEST,&isnest);
3258 ierr = MatNestGetSize(pA,&nr,NULL); PCHKERRQ(pc,ierr);
3259 ierr = PetscCalloc1(nr,&isrow); CCHKERRQ(PETSC_COMM_SELF,ierr);
3260 ierr = MatNestGetISs(pA,isrow,NULL); PCHKERRQ(pc,ierr);
3270 ierr = PCFieldSplitSetIS(pc,NULL,isrow[i]); PCHKERRQ(pc,ierr);
3272 ierr = PetscFree(isrow); CCHKERRQ(PETSC_COMM_SELF,ierr);
3278 const std::string &prefix)
3283 ierr = SNESCreate(comm, &snes); CCHKERRQ(comm, ierr);
3285 ierr = PetscObjectGetClassId(
obj, &
cid); PCHKERRQ(
obj, ierr);
3286 ierr = SNESSetOptionsPrefix(snes, prefix.c_str()); PCHKERRQ(snes, ierr);
3293 const std::string &prefix)
3298 ierr = SNESCreate(comm, &snes); CCHKERRQ(comm, ierr);
3300 ierr = PetscObjectGetClassId(
obj, &
cid); PCHKERRQ(
obj, ierr);
3301 ierr = SNESSetOptionsPrefix(snes, prefix.c_str()); PCHKERRQ(snes, ierr);
3313 ierr = PetscObjectGetComm(
obj,&comm); PCHKERRQ(
obj, ierr);
3314 ierr = SNESDestroy(&snes); CCHKERRQ(comm, ierr);
3326 ierr = SNESGetFunction(snes, NULL, NULL, &fctx);
3327 PCHKERRQ(snes, ierr);
3328 ierr = SNESGetJacobian(snes, NULL, NULL, NULL, &jctx);
3329 PCHKERRQ(snes, ierr);
3332 (
void*)&op == fctx &&
3333 (
void*)&op == jctx);
3334 ierr = MPI_Allreduce(&ls,&gs,1,MPIU_BOOL,MPI_LAND,
3336 PCHKERRQ(snes,ierr);
3339 ierr = SNESReset(snes); PCHKERRQ(snes,ierr);
3350 ierr = SNESGetLineSearch(snes, &ls); PCHKERRQ(snes,ierr);
3351 ierr = SNESLineSearchSetType(ls, SNESLINESEARCHBT); PCHKERRQ(snes,ierr);
3354 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
3356 ierr = SNESSetFunction(snes, NULL, __mfem_snes_function, (
void *)snes_ctx);
3357 PCHKERRQ(snes, ierr);
3358 ierr = SNESSetJacobian(snes, NULL, NULL, __mfem_snes_jacobian,
3360 PCHKERRQ(snes, ierr);
3372 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
3373 snes_ctx->jacType = jacType;
3379 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
3380 snes_ctx->objective = objfn;
3383 ierr = SNESSetObjective(snes, __mfem_snes_objective, (
void *)snes_ctx);
3384 PCHKERRQ(snes, ierr);
3391 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
3392 snes_ctx->postcheck = post;
3396 ierr = SNESGetLineSearch(snes, &ls); PCHKERRQ(snes,ierr);
3397 ierr = SNESLineSearchSetPostCheck(ls, __mfem_snes_postcheck, (
void *)snes_ctx);
3407 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)
private_ctx;
3408 snes_ctx->update = update;
3411 ierr = SNESSetUpdate(snes, __mfem_snes_update); PCHKERRQ(snes, ierr);
3418 bool b_nonempty = b.
Size();
3422 if (b_nonempty) { B->PlaceArray(b.
GetData()); }
3430 ierr = SNESSolve(snes, B->x, X->x); PCHKERRQ(snes, ierr);
3432 if (b_nonempty) { B->ResetArray(); }
3442 ierr = TSCreate(comm,&ts); CCHKERRQ(comm,ierr);
3444 ierr = PetscObjectGetClassId(
obj,&
cid); PCHKERRQ(
obj,ierr);
3445 ierr = TSSetOptionsPrefix(ts, prefix.c_str()); PCHKERRQ(ts, ierr);
3451 ierr = TSSetMaxSteps(ts,PETSC_MAX_INT-1);
3453 ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);
3456 ierr = TSGetAdapt(ts,&tsad);
3458 ierr = TSAdaptSetType(tsad,TSADAPTNONE);
3466 ierr = PetscObjectGetComm(
obj,&comm); PCHKERRQ(
obj,ierr);
3467 ierr = TSDestroy(&ts); CCHKERRQ(comm,ierr);
3475 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
3478 ierr = TSReset(ts); PCHKERRQ(ts,ierr);
3481 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
3482 ts_ctx->cached_ijacstate = -1;
3483 ts_ctx->cached_rhsjacstate = -1;
3484 ts_ctx->cached_splits_xstate = -1;
3485 ts_ctx->cached_splits_xdotstate = -1;
3493 ierr = TSSetIFunction(ts, NULL, __mfem_ts_ifunction, (
void *)ts_ctx);
3495 ierr = TSSetIJacobian(ts, NULL, NULL, __mfem_ts_ijacobian, (
void *)ts_ctx);
3497 ierr = TSSetEquationType(ts, TS_EQ_IMPLICIT);
3504 ierr = TSSetEquationType(ts, TS_EQ_EXPLICIT);
3507 ierr = TSSetRHSFunction(ts, NULL, __mfem_ts_rhsfunction, (
void *)ts_ctx);
3509 ierr = TSSetRHSJacobian(ts, NULL, NULL, __mfem_ts_rhsjacobian, (
void *)ts_ctx);
3518 ierr = TSSetSolution(ts,X); PCHKERRQ(ts,ierr);
3521 PetscBool use = PETSC_TRUE;
3522 ierr = PetscOptionsGetBool(NULL,NULL,
"-mfem_use_splitjac",&use,NULL);
3525 ierr = PetscObjectComposeFunction((
PetscObject)ts,
"TSComputeSplitJacobians_C",
3526 __mfem_ts_computesplits);
3531 ierr = PetscObjectComposeFunction((
PetscObject)ts,
"TSComputeSplitJacobians_C",
3539 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
3540 ts_ctx->jacType = jacType;
3545 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
3546 return ts_ctx->type;
3551 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
3554 ts_ctx->type = type;
3557 ierr = TSSetProblemType(ts, TS_LINEAR);
3562 ierr = TSSetProblemType(ts, TS_NONLINEAR);
3571 ierr = TSSetTime(ts, t); PCHKERRQ(ts, ierr);
3572 ierr = TSSetTimeStep(ts, dt); PCHKERRQ(ts, ierr);
3580 ierr = TSSetSolution(ts, *X); PCHKERRQ(ts, ierr);
3581 ierr = TSStep(ts); PCHKERRQ(ts, ierr);
3587 ierr = TSGetTime(ts,&pt); PCHKERRQ(ts,ierr);
3596 ierr = TSSetTime(ts, t); PCHKERRQ(ts, ierr);
3597 ierr = TSSetTimeStep(ts, dt); PCHKERRQ(ts, ierr);
3598 ierr = TSSetMaxTime(ts, t_final); PCHKERRQ(ts, ierr);
3599 ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
3611 __mfem_ts_ctx *ts_ctx = (__mfem_ts_ctx*)
private_ctx;
3612 ts_ctx->cached_shift = std::numeric_limits<PetscReal>::min();
3613 ts_ctx->cached_ijacstate = -1;
3614 ts_ctx->cached_rhsjacstate = -1;
3615 ts_ctx->cached_splits_xstate = -1;
3616 ts_ctx->cached_splits_xdotstate = -1;
3619 ierr = TSSolve(ts, X->x); PCHKERRQ(ts, ierr);
3624 ierr = TSGetTime(ts, &pt); PCHKERRQ(ts,ierr);
3626 ierr = TSGetTimeStep(ts,&pt); PCHKERRQ(ts,ierr);
3632 #include "petsc/private/petscimpl.h"
3633 #include "petsc/private/matimpl.h"
3639 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)ctx;
3641 PetscFunctionBeginUser;
3644 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
3656 PetscFunctionReturn(0);
3659 static PetscErrorCode __mfem_ts_ifunction(
TS ts,
PetscReal t, Vec x, Vec xp,
3662 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)ctx;
3663 PetscErrorCode ierr;
3665 PetscFunctionBeginUser;
3673 if (ts_ctx->bchandler)
3678 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(xx.Size()); }
3679 if (!ts_ctx->work2) { ts_ctx->work2 =
new mfem::Vector(xx.Size()); }
3685 bchandler->
ZeroBC(yy,*txp);
3697 ierr = PetscObjectStateIncrease((
PetscObject)f); CHKERRQ(ierr);
3698 PetscFunctionReturn(0);
3701 static PetscErrorCode __mfem_ts_rhsfunction(
TS ts,
PetscReal t, Vec x, Vec f,
3704 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)ctx;
3705 PetscErrorCode ierr;
3707 PetscFunctionBeginUser;
3708 if (ts_ctx->bchandler) { MFEM_ABORT(
"RHS evaluation with bc not implemented"); }
3718 ierr = PetscObjectStateIncrease((
PetscObject)f); CHKERRQ(ierr);
3719 PetscFunctionReturn(0);
3722 static PetscErrorCode __mfem_ts_ijacobian(
TS ts,
PetscReal t, Vec x,
3726 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)ctx;
3731 PetscObjectState state;
3732 PetscErrorCode ierr;
3734 PetscFunctionBeginUser;
3738 ierr = PetscObjectStateGet((
PetscObject)A,&state); CHKERRQ(ierr);
3740 std::abs(ts_ctx->cached_shift/shift - 1.0) < eps &&
3741 state == ts_ctx->cached_ijacstate) { PetscFunctionReturn(0); }
3748 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
3749 ierr = VecGetArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
3751 ierr = VecRestoreArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
3752 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
3753 if (!ts_ctx->bchandler)
3760 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
3767 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
3771 if (!ts_ctx->bchandler) {
delete xx; }
3772 ts_ctx->cached_shift = shift;
3775 bool delete_pA =
false;
3779 pA->
GetType() != ts_ctx->jacType))
3787 if (ts_ctx->bchandler)
3795 PetscObjectState nonzerostate;
3796 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
3801 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
3802 if (delete_pA) {
delete pA; }
3807 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3808 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3821 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
3823 if (isnest) { P->nonzerostate = nonzerostate + 1; }
3826 ierr = PetscObjectStateGet((
PetscObject)P,&ts_ctx->cached_ijacstate);
3832 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
3833 ierr = TSGetDM(ts,&dm); CHKERRQ(ierr);
3834 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
3835 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
3836 PetscFunctionReturn(0);
3839 static PetscErrorCode __mfem_ts_computesplits(
TS ts,
PetscReal t,Vec x,Vec xp,
3843 __mfem_ts_ctx* ts_ctx;
3847 PetscObjectState state;
3848 PetscBool rx = PETSC_TRUE, rxp = PETSC_TRUE;
3849 PetscBool assembled;
3850 PetscErrorCode ierr;
3852 PetscFunctionBeginUser;
3853 ierr = TSGetIJacobian(ts,NULL,NULL,NULL,(
void**)&ts_ctx); CHKERRQ(ierr);
3856 ierr = PetscObjectStateGet((
PetscObject)Jx,&state); CHKERRQ(ierr);
3858 state == ts_ctx->cached_splits_xstate) { rx = PETSC_FALSE; }
3859 ierr = PetscObjectStateGet((
PetscObject)Jxp,&state); CHKERRQ(ierr);
3861 state == ts_ctx->cached_splits_xdotstate) { rxp = PETSC_FALSE; }
3862 if (!rx && !rxp) { PetscFunctionReturn(0); }
3869 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
3870 ierr = VecGetArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
3872 ierr = VecRestoreArrayRead(xp,(
const PetscScalar**)&array); CHKERRQ(ierr);
3873 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
3874 if (!ts_ctx->bchandler)
3881 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
3888 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
3897 bool delete_mat =
false;
3901 pJx->
GetType() != ts_ctx->jacType))
3906 ierr = PetscObjectReference((
PetscObject)B); CHKERRQ(ierr);
3914 ierr = MatAssembled(Jx,&assembled); CHKERRQ(ierr);
3917 ierr = MatCopy(*pJx,Jx,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
3922 ierr = MatDuplicate(*pJx,MAT_COPY_VALUES,&B); CHKERRQ(ierr);
3923 ierr = MatHeaderReplace(Jx,&B); CHKERRQ(ierr);
3926 if (delete_mat) {
delete pJx; }
3930 if (ts_ctx->bchandler)
3947 pJxp->
GetType() != ts_ctx->jacType))
3952 ierr = PetscObjectReference((
PetscObject)B); CHKERRQ(ierr);
3955 &oJxp,ts_ctx->jacType);
3959 ierr = MatAssembled(Jxp,&assembled); CHKERRQ(ierr);
3962 ierr = MatCopy(*pJxp,Jxp,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
3967 ierr = MatDuplicate(*pJxp,MAT_COPY_VALUES,&B); CHKERRQ(ierr);
3968 ierr = MatHeaderReplace(Jxp,&B); CHKERRQ(ierr);
3970 if (delete_mat) {
delete pJxp; }
3974 if (ts_ctx->bchandler)
3985 ierr = MatAXPY(*pJxp,-1.0,*pJx,SAME_NONZERO_PATTERN); PCHKERRQ(ts,ierr);
3991 ierr = MatAssemblyBegin(Ax,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3992 ierr = MatAssemblyEnd(Ax,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3994 if (Axp && Axp != Jxp)
3996 ierr = MatAssemblyBegin(Axp,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
3997 ierr = MatAssemblyEnd(Axp,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4001 ierr = PetscObjectStateGet((
PetscObject)Jx,&ts_ctx->cached_splits_xstate);
4003 ierr = PetscObjectStateGet((
PetscObject)Jxp,&ts_ctx->cached_splits_xdotstate);
4008 if (!ts_ctx->bchandler) {
delete xx; }
4009 PetscFunctionReturn(0);
4012 static PetscErrorCode __mfem_ts_rhsjacobian(
TS ts,
PetscReal t, Vec x,
4015 __mfem_ts_ctx* ts_ctx = (__mfem_ts_ctx*)ctx;
4019 PetscObjectState state;
4020 PetscErrorCode ierr;
4022 PetscFunctionBeginUser;
4024 ierr = PetscObjectStateGet((
PetscObject)A,&state); CHKERRQ(ierr);
4026 state == ts_ctx->cached_rhsjacstate) { PetscFunctionReturn(0); }
4033 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4034 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4035 if (!ts_ctx->bchandler)
4042 if (!ts_ctx->work) { ts_ctx->work =
new mfem::Vector(n); }
4049 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4053 if (!ts_ctx->bchandler) {
delete xx; }
4056 bool delete_pA =
false;
4060 pA->
GetType() != ts_ctx->jacType))
4068 if (ts_ctx->bchandler)
4076 PetscObjectState nonzerostate;
4077 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
4082 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
4083 if (delete_pA) {
delete pA; }
4095 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
4097 if (isnest) { P->nonzerostate = nonzerostate + 1; }
4102 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4103 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4109 ierr = TSRHSJacobianSetReuse(ts,PETSC_TRUE); PCHKERRQ(ts,ierr);
4111 ierr = PetscObjectStateGet((
PetscObject)A,&ts_ctx->cached_rhsjacstate);
4117 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
4118 ierr = TSGetDM(ts,&dm); CHKERRQ(ierr);
4119 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
4120 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
4121 PetscFunctionReturn(0);
4127 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)ctx;
4129 PetscFunctionBeginUser;
4132 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
4141 PetscErrorCode ierr;
4143 ierr = SNESGetSolution(snes,&x); CHKERRQ(ierr);
4150 PetscErrorCode ierr;
4152 ierr = SNESGetFunction(snes,&x,NULL,NULL); CHKERRQ(ierr);
4157 PetscFunctionReturn(0);
4160 static PetscErrorCode __mfem_snes_jacobian(
SNES snes, Vec x,
Mat A,
Mat P,
4165 PetscErrorCode ierr;
4167 __mfem_snes_ctx *snes_ctx = (__mfem_snes_ctx*)ctx;
4169 PetscFunctionBeginUser;
4170 ierr = VecGetArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4171 ierr = VecGetLocalSize(x,&n); CHKERRQ(ierr);
4172 if (!snes_ctx->bchandler)
4179 if (!snes_ctx->work) { snes_ctx->work =
new mfem::Vector(n); }
4182 xx = snes_ctx->work;
4188 ierr = VecRestoreArrayRead(x,(
const PetscScalar**)&array); CHKERRQ(ierr);
4189 if (!snes_ctx->bchandler) {
delete xx; }
4192 bool delete_pA =
false;
4196 pA->
GetType() != snes_ctx->jacType))
4204 if (snes_ctx->bchandler)
4212 PetscObjectState nonzerostate;
4213 ierr = MatGetNonzeroState(P,&nonzerostate); CHKERRQ(ierr);
4217 ierr = MatHeaderReplace(P,&B); CHKERRQ(ierr);
4218 if (delete_pA) {
delete pA; }
4230 ierr = PetscObjectTypeCompare((
PetscObject)P,MATNEST,&isnest);
4232 if (isnest) { P->nonzerostate = nonzerostate + 1; }
4237 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4238 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4244 ierr = MatGetType(P,&mtype); CHKERRQ(ierr);
4245 ierr = SNESGetDM(snes,&dm); CHKERRQ(ierr);
4246 ierr = DMSetMatType(dm,mtype); CHKERRQ(ierr);
4247 ierr = DMShellSetMatrix(dm,P); CHKERRQ(ierr);
4248 PetscFunctionReturn(0);
4251 static PetscErrorCode __mfem_snes_function(
SNES snes, Vec x, Vec f,
void *ctx)
4253 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)ctx;
4255 PetscFunctionBeginUser;
4258 if (snes_ctx->bchandler)
4265 snes_ctx->op->Mult(*txx,ff);
4272 snes_ctx->op->Mult(xx,ff);
4275 ierr = PetscObjectStateIncrease((
PetscObject)f); CHKERRQ(ierr);
4276 PetscFunctionReturn(0);
4279 static PetscErrorCode __mfem_snes_objective(
SNES snes, Vec x,
PetscReal *f,
4282 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)ctx;
4284 PetscFunctionBeginUser;
4285 if (!snes_ctx->objective)
4287 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing objective function");
4291 (*snes_ctx->objective)(snes_ctx->op,xx,&lf);
4293 PetscFunctionReturn(0);
4296 static PetscErrorCode __mfem_snes_postcheck(SNESLineSearch ls,Vec X,Vec Y,Vec W,
4297 PetscBool *cy,PetscBool *cw,
void* ctx)
4299 __mfem_snes_ctx* snes_ctx = (__mfem_snes_ctx*)ctx;
4300 bool lcy =
false,lcw =
false;
4302 PetscFunctionBeginUser;
4306 (*snes_ctx->postcheck)(snes_ctx->op,x,y,w,lcy,lcw);
4307 if (lcy) { *cy = PETSC_TRUE; }
4308 if (lcw) { *cw = PETSC_TRUE; }
4309 PetscFunctionReturn(0);
4312 static PetscErrorCode __mfem_snes_update(
SNES snes,
PetscInt it)
4315 __mfem_snes_ctx* snes_ctx;
4317 PetscFunctionBeginUser;
4319 ierr = SNESGetFunction(snes,&F,NULL,(
void **)&snes_ctx); CHKERRQ(ierr);
4320 ierr = SNESGetSolution(snes,&X); CHKERRQ(ierr);
4323 ierr = VecDuplicate(X,&pX); CHKERRQ(ierr);
4326 ierr = VecDestroy(&pX); CHKERRQ(ierr);
4330 if (!pX) SETERRQ(PetscObjectComm((
PetscObject)snes),PETSC_ERR_USER,
4331 "Missing previous solution");
4332 ierr = SNESGetSolutionUpdate(snes,&dX); CHKERRQ(ierr);
4337 (*snes_ctx->update)(snes_ctx->op,it,f,x,dx,px);
4339 ierr = VecCopy(X,pX); CHKERRQ(ierr);
4340 PetscFunctionReturn(0);
4346 __mfem_monitor_ctx *monctx = (__mfem_monitor_ctx*)ctx;
4348 PetscFunctionBeginUser;
4351 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,
"Missing monitor context");
4360 PetscErrorCode ierr;
4362 ierr = KSPBuildSolution(ksp,NULL,&x); CHKERRQ(ierr);
4369 PetscErrorCode ierr;
4371 ierr = KSPBuildResidual(ksp,NULL,NULL,&x); CHKERRQ(ierr);
4376 PetscFunctionReturn(0);
4379 static PetscErrorCode __mfem_mat_shell_apply(
Mat A, Vec x, Vec y)
4382 PetscErrorCode ierr;
4384 PetscFunctionBeginUser;
4385 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
4386 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
4391 ierr = PetscObjectStateIncrease((
PetscObject)y); CHKERRQ(ierr);
4392 PetscFunctionReturn(0);
4395 static PetscErrorCode __mfem_mat_shell_apply_transpose(
Mat A, Vec x, Vec y)
4398 PetscErrorCode ierr;
4400 PetscFunctionBeginUser;
4401 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
4402 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
4407 ierr = PetscObjectStateIncrease((
PetscObject)y); CHKERRQ(ierr);
4408 PetscFunctionReturn(0);
4411 static PetscErrorCode __mfem_mat_shell_copy(
Mat A,
Mat B, MatStructure str)
4414 PetscErrorCode ierr;
4416 PetscFunctionBeginUser;
4417 ierr = MatShellGetContext(A,(
void **)&op); CHKERRQ(ierr);
4418 if (!op) { SETERRQ(PetscObjectComm((
PetscObject)A),PETSC_ERR_LIB,
"Missing operator"); }
4419 ierr = MatShellSetContext(B,(
void *)op); CHKERRQ(ierr);
4420 PetscFunctionReturn(0);
4423 static PetscErrorCode __mfem_mat_shell_destroy(
Mat A)
4425 PetscFunctionBeginUser;
4426 PetscFunctionReturn(0);
4429 static PetscErrorCode __mfem_pc_shell_view(
PC pc, PetscViewer viewer)
4431 __mfem_pc_shell_ctx *
ctx;
4432 PetscErrorCode ierr;
4434 PetscFunctionBeginUser;
4435 ierr = PCShellGetContext(pc,(
void **)&ctx); CHKERRQ(ierr);
4439 ierr = PetscObjectTypeCompare((
PetscObject)viewer,PETSCVIEWERASCII,&isascii);
4446 ierr = PCView(*ppc,viewer); CHKERRQ(ierr);
4452 ierr = PetscViewerASCIIPrintf(viewer,
4453 "No information available on the mfem::Solver\n");
4457 if (isascii && ctx->factory)
4459 ierr = PetscViewerASCIIPrintf(viewer,
4460 "Number of preconditioners created by the factory %lu\n",ctx->numprec);
4464 PetscFunctionReturn(0);
4467 static PetscErrorCode __mfem_pc_shell_apply(
PC pc, Vec x, Vec y)
4469 __mfem_pc_shell_ctx *
ctx;
4470 PetscErrorCode ierr;
4472 PetscFunctionBeginUser;
4475 ierr = PCShellGetContext(pc,(
void **)&ctx); CHKERRQ(ierr);
4478 ctx->op->Mult(xx,yy);
4480 ierr = PetscObjectStateIncrease((
PetscObject)y); CHKERRQ(ierr);
4486 PetscFunctionReturn(0);
4489 static PetscErrorCode __mfem_pc_shell_apply_transpose(
PC pc, Vec x, Vec y)
4491 __mfem_pc_shell_ctx *
ctx;
4492 PetscErrorCode ierr;
4494 PetscFunctionBeginUser;
4497 ierr = PCShellGetContext(pc,(
void **)&ctx); CHKERRQ(ierr);
4500 ctx->op->MultTranspose(xx,yy);
4502 ierr = PetscObjectStateIncrease((
PetscObject)y); CHKERRQ(ierr);
4508 PetscFunctionReturn(0);
4511 static PetscErrorCode __mfem_pc_shell_setup(
PC pc)
4513 __mfem_pc_shell_ctx *
ctx;
4515 PetscFunctionBeginUser;
4516 ierr = PCShellGetContext(pc,(
void **)&ctx); CHKERRQ(ierr);
4527 ierr = PCGetOperators(pc,NULL,&B); CHKERRQ(ierr);
4536 PetscFunctionReturn(0);
4539 static PetscErrorCode __mfem_pc_shell_destroy(
PC pc)
4541 __mfem_pc_shell_ctx *
ctx;
4542 PetscErrorCode ierr;
4544 PetscFunctionBeginUser;
4545 ierr = PCShellGetContext(pc,(
void **)&ctx); CHKERRQ(ierr);
4551 PetscFunctionReturn(0);
4554 static PetscErrorCode __mfem_array_container_destroy(
void *ptr)
4556 PetscErrorCode ierr;
4558 PetscFunctionBeginUser;
4559 ierr = PetscFree(ptr); CHKERRQ(ierr);
4560 PetscFunctionReturn(0);
4563 static PetscErrorCode __mfem_matarray_container_destroy(
void *ptr)
4566 PetscErrorCode ierr;
4568 PetscFunctionBeginUser;
4569 for (
int i=0; i<a->
Size(); i++)
4573 ierr = MatDestroy(&M); CCHKERRQ(comm,ierr);
4576 PetscFunctionReturn(0);
4579 static PetscErrorCode __mfem_monitor_ctx_destroy(
void **ctx)
4581 PetscErrorCode ierr;
4583 PetscFunctionBeginUser;
4584 ierr = PetscFree(*ctx); CHKERRQ(ierr);
4585 PetscFunctionReturn(0);
4590 PetscErrorCode MakeShellPC(
PC pc,
mfem::Solver &precond,
bool ownsop)
4592 PetscFunctionBeginUser;
4593 __mfem_pc_shell_ctx *ctx =
new __mfem_pc_shell_ctx;
4595 ctx->ownsop = ownsop;
4596 ctx->factory = NULL;
4602 ierr = PCSetType(pc,PCNONE); CHKERRQ(ierr);
4604 ierr = PCSetType(pc,PCSHELL); CHKERRQ(ierr);
4605 ierr = PCShellSetName(pc,
"MFEM Solver (unknown Pmat)"); CHKERRQ(ierr);
4606 ierr = PCShellSetContext(pc,(
void *)ctx); CHKERRQ(ierr);
4607 ierr = PCShellSetApply(pc,__mfem_pc_shell_apply); CHKERRQ(ierr);
4608 ierr = PCShellSetApplyTranspose(pc,__mfem_pc_shell_apply_transpose);
4610 ierr = PCShellSetSetUp(pc,__mfem_pc_shell_setup); CHKERRQ(ierr);
4611 ierr = PCShellSetView(pc,__mfem_pc_shell_view); CHKERRQ(ierr);
4612 ierr = PCShellSetDestroy(pc,__mfem_pc_shell_destroy); CHKERRQ(ierr);
4613 PetscFunctionReturn(0);
4618 PetscErrorCode MakeShellPCWithFactory(
PC pc,
4621 PetscFunctionBeginUser;
4622 __mfem_pc_shell_ctx *ctx =
new __mfem_pc_shell_ctx;
4625 ctx->factory = factory;
4631 ierr = PCSetType(pc,PCNONE); CHKERRQ(ierr);
4633 ierr = PCSetType(pc,PCSHELL); CHKERRQ(ierr);
4634 ierr = PCShellSetName(pc,factory->
GetName()); CHKERRQ(ierr);
4635 ierr = PCShellSetContext(pc,(
void *)ctx); CHKERRQ(ierr);
4636 ierr = PCShellSetApply(pc,__mfem_pc_shell_apply); CHKERRQ(ierr);
4637 ierr = PCShellSetApplyTranspose(pc,__mfem_pc_shell_apply_transpose);
4639 ierr = PCShellSetSetUp(pc,__mfem_pc_shell_setup); CHKERRQ(ierr);
4640 ierr = PCShellSetView(pc,__mfem_pc_shell_view); CHKERRQ(ierr);
4641 ierr = PCShellSetDestroy(pc,__mfem_pc_shell_destroy); CHKERRQ(ierr);
4642 PetscFunctionReturn(0);
4647 static PetscErrorCode Convert_Array_IS(MPI_Comm comm,
bool islist,
4652 const int *data = list ? list->
GetData() : NULL;
4653 PetscErrorCode ierr;
4655 PetscFunctionBeginUser;
4656 ierr = PetscMalloc1(n,&idxs); CHKERRQ(ierr);
4659 for (
PetscInt i=0; i<n; i++) { idxs[i] = data[i] + st; }
4666 if (data[i]) { idxs[cum++] = i+st; }
4670 ierr = ISCreateGeneral(comm,n,idxs,PETSC_OWN_POINTER,is);
4672 PetscFunctionReturn(0);
4678 static PetscErrorCode Convert_Vmarks_IS(MPI_Comm comm,
4686 PetscErrorCode ierr;
4688 PetscFunctionBeginUser;
4689 for (
int i = 0; i < pl2l.
Size(); i++)
4693 ierr = MatGetRowIJ(pl2l[i],0,PETSC_FALSE,PETSC_FALSE,&m,(
const PetscInt**)&ii,
4694 (
const PetscInt**)&jj,&done); CHKERRQ(ierr);
4695 MFEM_VERIFY(done,
"Unable to perform MatGetRowIJ on " << i <<
" l2l matrix");
4696 ierr = MatGetSize(pl2l[i],NULL,&n); CHKERRQ(ierr);
4697 #if defined(PETSC_USE_64BIT_INDICES)
4698 int nnz = (int)ii[m];
4699 int *mii =
new int[m+1];
4700 int *mjj =
new int[nnz];
4701 for (
int j = 0; j < m+1; j++) { mii[j] = (int)ii[j]; }
4702 for (
int j = 0; j < nnz; j++) { mjj[j] = (int)jj[j]; }
4707 ierr = MatRestoreRowIJ(pl2l[i],0,PETSC_FALSE,PETSC_FALSE,&m,
4709 (
const PetscInt**)&jj,&done); CHKERRQ(ierr);
4710 MFEM_VERIFY(done,
"Unable to perform MatRestoreRowIJ on "
4711 << i <<
" l2l matrix");
4714 for (
int i = 0; i < l2l.Size(); i++) { nl += l2l[i]->Width(); }
4716 const int* vdata = mark->
GetData();
4717 int* sdata = sub_dof_marker.
GetData();
4718 int cumh = 0, cumw = 0;
4719 for (
int i = 0; i < l2l.Size(); i++)
4724 l2l[i]->BooleanMultTranspose(vf_marker,sf_marker);
4725 cumh += l2l[i]->Height();
4726 cumw += l2l[i]->Width();
4728 ierr = Convert_Array_IS(comm,
false,&sub_dof_marker,st,is); CCHKERRQ(comm,ierr);
4729 for (
int i = 0; i < pl2l.
Size(); i++)
4733 PetscFunctionReturn(0);
4736 #if !defined(PETSC_HAVE_HYPRE)
4738 #if defined(HYPRE_MIXEDINT)
4739 #error "HYPRE_MIXEDINT not supported"
4742 #include "_hypre_parcsr_mv.h"
4743 static PetscErrorCode MatConvert_hypreParCSR_AIJ(hypre_ParCSRMatrix* hA,
Mat* pA)
4745 MPI_Comm comm = hypre_ParCSRMatrixComm(hA);
4746 hypre_CSRMatrix *hdiag,*hoffd;
4748 PetscInt *dii,*djj,*oii,*ojj,*iptr;
4751 PetscErrorCode ierr;
4753 PetscFunctionBeginUser;
4754 hdiag = hypre_ParCSRMatrixDiag(hA);
4755 hoffd = hypre_ParCSRMatrixOffd(hA);
4756 m = hypre_CSRMatrixNumRows(hdiag);
4757 n = hypre_CSRMatrixNumCols(hdiag);
4758 dnnz = hypre_CSRMatrixNumNonzeros(hdiag);
4759 onnz = hypre_CSRMatrixNumNonzeros(hoffd);
4760 ierr = PetscMalloc1(m+1,&dii); CHKERRQ(ierr);
4761 ierr = PetscMalloc1(dnnz,&djj); CHKERRQ(ierr);
4762 ierr = PetscMalloc1(dnnz,&da); CHKERRQ(ierr);
4763 ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*
sizeof(
PetscInt));
4765 ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*
sizeof(
PetscInt));
4767 ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*
sizeof(
PetscScalar));
4774 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr); CHKERRQ(ierr);
4778 ierr = MPI_Comm_size(comm,&size); CHKERRQ(ierr);
4783 ierr = PetscMalloc1(m+1,&oii); CHKERRQ(ierr);
4784 ierr = PetscMalloc1(onnz,&ojj); CHKERRQ(ierr);
4785 ierr = PetscMalloc1(onnz,&oa); CHKERRQ(ierr);
4786 ierr = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*
sizeof(
PetscInt));
4788 offdj = hypre_CSRMatrixJ(hoffd);
4789 coffd = hypre_ParCSRMatrixColMapOffd(hA);
4790 for (i=0; i<onnz; i++) { ojj[i] = coffd[offdj[i]]; }
4791 ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*
sizeof(
PetscScalar));
4798 ierr = PetscSortIntWithScalarArray(nc,iptr,aptr); CHKERRQ(ierr);
4802 ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,
4803 djj,da,oii,ojj,oa,pA); CHKERRQ(ierr);
4809 ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,pA); CHKERRQ(ierr);
4815 void *ptrs[6] = {dii,djj,da,oii,ojj,oa};
4816 const char *names[6] = {
"_mfem_csr_dii",
4827 ierr = PetscContainerCreate(comm,&c); CHKERRQ(ierr);
4828 ierr = PetscContainerSetPointer(c,ptrs[i]); CHKERRQ(ierr);
4829 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
4833 ierr = PetscContainerDestroy(&c); CHKERRQ(ierr);
4835 PetscFunctionReturn(0);
4838 static PetscErrorCode MatConvert_hypreParCSR_IS(hypre_ParCSRMatrix* hA,
Mat* pA)
4841 ISLocalToGlobalMapping rl2g,cl2g;
4843 hypre_CSRMatrix *hdiag,*hoffd;
4844 MPI_Comm comm = hypre_ParCSRMatrixComm(hA);
4846 const char *names[2] = {
"_mfem_csr_aux",
4850 PetscInt *col_map_offd,*hdi,*hdj,*hoi,*hoj;
4852 PetscInt cum,dr,dc,oc,str,stc,nnz,i,jd,jo;
4853 PetscErrorCode ierr;
4855 PetscFunctionBeginUser;
4857 str = hypre_ParCSRMatrixFirstRowIndex(hA);
4858 stc = hypre_ParCSRMatrixFirstColDiag(hA);
4859 hdiag = hypre_ParCSRMatrixDiag(hA);
4860 hoffd = hypre_ParCSRMatrixOffd(hA);
4861 dr = hypre_CSRMatrixNumRows(hdiag);
4862 dc = hypre_CSRMatrixNumCols(hdiag);
4863 nnz = hypre_CSRMatrixNumNonzeros(hdiag);
4864 hdi = hypre_CSRMatrixI(hdiag);
4865 hdj = hypre_CSRMatrixJ(hdiag);
4866 hdd = hypre_CSRMatrixData(hdiag);
4867 oc = hypre_CSRMatrixNumCols(hoffd);
4868 nnz += hypre_CSRMatrixNumNonzeros(hoffd);
4869 hoi = hypre_CSRMatrixI(hoffd);
4870 hoj = hypre_CSRMatrixJ(hoffd);
4871 hod = hypre_CSRMatrixData(hoffd);
4874 ierr = ISCreateStride(comm,dr,str,1,&is); CHKERRQ(ierr);
4875 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g); CHKERRQ(ierr);
4876 ierr = ISDestroy(&is); CHKERRQ(ierr);
4877 col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
4878 ierr = PetscMalloc1(dc+oc,&aux); CHKERRQ(ierr);
4879 for (i=0; i<dc; i++) { aux[i] = i+stc; }
4880 for (i=0; i<oc; i++) { aux[i+dc] = col_map_offd[i]; }
4881 ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is); CHKERRQ(ierr);
4882 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g); CHKERRQ(ierr);
4883 ierr = ISDestroy(&is); CHKERRQ(ierr);
4886 ierr = MatCreate(comm,pA); CHKERRQ(ierr);
4887 ierr = MatSetSizes(*pA,dr,dc,PETSC_DECIDE,PETSC_DECIDE); CHKERRQ(ierr);
4888 ierr = MatSetType(*pA,MATIS); CHKERRQ(ierr);
4889 ierr = MatSetLocalToGlobalMapping(*pA,rl2g,cl2g); CHKERRQ(ierr);
4890 ierr = ISLocalToGlobalMappingDestroy(&rl2g); CHKERRQ(ierr);
4891 ierr = ISLocalToGlobalMappingDestroy(&cl2g); CHKERRQ(ierr);
4894 ierr = PetscMalloc1(nnz+dr+1,&aux); CHKERRQ(ierr);
4895 ierr = PetscMalloc1(nnz,&data); CHKERRQ(ierr);
4899 *ii = *(hdi++) + *(hoi++);
4900 for (jd=0,jo=0,cum=0; *ii<nnz; cum++)
4904 for (; jd<*hdi; jd++) { *jj++ = *hdj++; *aa++ = *hdd++; }
4905 for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
4906 *(++ii) = *(hdi++) + *(hoi++);
4907 ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold); CHKERRQ(ierr);
4909 for (; cum<dr; cum++) { *(++ii) = nnz; }
4913 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,ii,jj,aa,&lA);
4921 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c); CHKERRQ(ierr);
4922 ierr = PetscContainerSetPointer(c,ptrs[i]); CHKERRQ(ierr);
4923 ierr = PetscContainerSetUserDestroy(c,__mfem_array_container_destroy);
4927 ierr = PetscContainerDestroy(&c); CHKERRQ(ierr);
4929 ierr = MatISSetLocalMat(*pA,lA); CHKERRQ(ierr);
4930 ierr = MatDestroy(&lA); CHKERRQ(ierr);
4931 ierr = MatAssemblyBegin(*pA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4932 ierr = MatAssemblyEnd(*pA,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4933 PetscFunctionReturn(0);
4937 #endif // MFEM_USE_PETSC
4938 #endif // MFEM_USE_MPI
int Size() const
Return the logical size of the array.
void SetPreconditioner(Solver &precond)
void SetPrintLevel(int plev)
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
PetscParVector * B
Right-hand side and solution vector.
void CreatePrivateContext()
void Print(const char *fname=NULL, bool binary=false) const
Prints the matrix (to stdout if fname is NULL)
Vector()
Default constructor for Vector. Sets size = 0 and data = NULL.
void trans(const Vector &u, Vector &x)
MPI_Comm GetComm() const
MPI communicator.
bool isImplicit() const
True if type is IMPLICIT or HOMOGENEOUS.
bool isHomogeneous() const
True if type is HOMOGENEOUS.
virtual void SetOperator(const Operator &op)
Specification of the nonlinear operator.
void MakeDataOwner() const
Set the Vector data (host pointer) ownership flag.
Abstract class for PETSc's preconditioners.
PetscParMatrix & operator+=(const PetscParMatrix &B)
virtual void SetOperator(const Operator &op)
HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
Returns the matrix P^t * A * P.
bool clcustom
Boolean to handle SetFromOptions calls.
void SetObjective(void(*obj)(Operator *op, const Vector &x, double *f))
Specification of an objective function to be used for line search.
void ConvertOperator(MPI_Comm comm, const Operator &op, Mat *B, Operator::Type tid)
virtual void MultTranspose(const Vector &b, Vector &x) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Wrapper for PETSc's matrix class.
PetscParVector & operator+=(const PetscParVector &y)
void ApplyBC(const Vector &x, Vector &y)
y = x on ess_tdof_list_c and y = g (internally evaluated) on ess_tdof_list
Abstract class for PETSc's linear solvers.
Vec x
The actual PETSc object.
void SetSize(int s)
Resize the vector to size s.
Abstract class for PETSc's solvers.
PetscODESolver::Type GetType() const
virtual void Run(Vector &x, double &t, double &dt, double t_final)
Perform time integration from time t [in] to time tf [in].
void SetPostCheck(void(*post)(Operator *op, const Vector &X, Vector &Y, Vector &W, bool &changed_y, bool &changed_w))
Base abstract class for first order time dependent operators.
PetscInt GetNumCols() const
Returns the local number of columns.
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void SetType(PetscODESolver::Type)
virtual void MonitorSolver(PetscSolver *solver)
Generic monitor to take access to the solver.
Pointer to an Operator of a specified type.
int * GetJ()
Return the array J.
void Mult(double a, const Vector &x, double b, Vector &y) const
Matvec: y = a A x + b y.
PetscBDDCSolver(MPI_Comm comm, Operator &op, const PetscBDDCSolverParams &opts=PetscBDDCSolverParams(), const std::string &prefix=std::string())
PetscParVector & AddValues(const Array< PetscInt > &, const Array< PetscScalar > &)
Add values in a vector.
void SetMat(Mat newA)
Replace the inner Mat Object. The reference count of newA is increased.
virtual ~PetscSolver()
Destroy the PetscParVectors allocated (if any).
PetscNonlinearSolver(MPI_Comm comm, const std::string &prefix=std::string())
T * GetData()
Returns the data.
virtual void SetTime(const double _t)
Set the current time.
virtual Operator & GetExplicitGradient(const Vector &x) const
Return an Operator representing dG/dx at the given point x and the currently set time.
int Size() const
Returns the size of the vector.
virtual void Step(Vector &x, double &t, double &dt)
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in]...
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
int * GetI()
Return the array I.
void Init()
Initialize with defaults. Does not initialize inherited members.
PetscPreconditioner(MPI_Comm comm, const std::string &prefix=std::string())
PetscClassId cid
The class id of the actual PETSc object.
ID for class PetscParMatrix, MATHYPRE format.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int IsZeroBlock(int i, int j) const
Check if block (i,j) is a zero block.
Abstract parallel finite element space.
void SetRelTol(double tol)
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
void Randomize(PetscInt seed=0)
Set random values.
PetscPCGSolver(MPI_Comm comm, const std::string &prefix=std::string())
void Destroy()
Delete all owned data. Does not perform re-initialization with defaults.
void SetMonitor(PetscSolverMonitor *ctx)
Sets user-defined monitoring routine.
void SetMaxIter(int max_iter)
double * GetData() const
Return a pointer to the beginning of the Vector data.
PetscParVector & operator*=(PetscScalar d)
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
void SortColumnIndices()
Sort the column indices corresponding to each row.
void EliminateRowsCols(const Array< int > &rows_cols, const PetscParVector &X, PetscParVector &B, double diag=1.)
Eliminate rows and columns from the matrix, and rows from the vector B. Modify B with the BC values i...
Wrapper for PETSc's vector class.
void Customize(bool customize=true) const
Customize object with options set.
PetscInt M() const
Returns the global number of rows.
Operator & GetBlock(int i, int j)
Return a reference to block i,j.
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 void Mult(const Vector &b, Vector &x) const
Application of the solver.
virtual ~PetscLinearSolver()
double * GetData()
Return the element data, i.e. the array A.
PetscInt GetNumRows() const
Returns the local number of rows.
virtual void ExplicitMult(const Vector &x, Vector &y) const
Perform the action of the explicit part of the operator, G: y = G(x, t) where t is the current time...
void Print(const char *fname=NULL, bool binary=false) const
Prints the vector (to stdout if fname is NULL)
void EliminateBC(HypreParMatrix &A, HypreParMatrix &Ae, const Array< int > &ess_dof_list, const Vector &X, Vector &B)
void ResetArray()
Reset the PETSc Vec object to use its default data. Call this method after the use of PlaceArray()...
PetscParVector & SetValues(const Array< PetscInt > &, const Array< PetscScalar > &)
Set values in a vector.
virtual void Init(TimeDependentOperator &f_, enum PetscODESolver::Type type)
Initialize the ODE solver.
PetscParMatrix * Transpose(bool action=false)
Returns the transpose of the PetscParMatrix.
ID for the base class Operator, i.e. any type.
PetscObject obj
The actual PETSc object (KSP, PC, SNES or TS).
Abstract class for monitoring PETSc's solvers.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
struct s_NavierContext ctx
void SetJacobianType(Operator::Type type)
int to_int(const std::string &str)
Convert a string to an int.
Auxiliary class for BDDC customization.
virtual ~PetscPreconditioner()
ID for class PetscParMatrix, unspecified format.
MPI_Comm GetComm() const
Get the associated MPI communicator.
void FixResidualBC(const Vector &x, Vector &y)
y = x-g on ess_tdof_list, the rest of y is unchanged
void LoseData()
NULL-ifies the data.
PetscParMatrix & operator=(const PetscParMatrix &B)
PetscInt GetColStart() const
Returns the global index of the first local column.
virtual ~PetscParVector()
Calls PETSc's destroy function.
PetscFieldSplitSolver(MPI_Comm comm, Operator &op, const std::string &prefix=std::string())
PetscBCHandler * bchandler
Handler for boundary conditions.
PetscParMatrix & operator-=(const PetscParMatrix &B)
virtual Solver * NewPreconditioner(const OperatorHandle &oh)=0
void ScaleRows(const Vector &s)
Scale the local row i by s(i).
void Zero(Vector &x)
Replace boundary dofs with 0.
void Assign(const T *)
Copy data from a pointer. 'Size()' elements are copied.
MPI_Comm GetComm() const
Get the associated MPI communicator.
void Shift(double s)
Shift diagonal by a constant.
ID for class PetscParMatrix, MATNEST format.
void SetTime(double t)
Sets the current time.
ID for class PetscParMatrix, MATSHELL format.
PetscParMatrix()
Create an empty matrix to be used as a reference to an existing matrix.
void SetBCHandler(PetscBCHandler *bch)
Sets the object to handle essential boundary conditions.
Wrapper for hypre's parallel vector class.
void ZeroBC(const Vector &x, Vector &y)
y = x on ess_tdof_list_c and y = 0 on ess_tdof_list
virtual void Eval(double t, Vector &g)
Boundary conditions evaluation.
Type
Enumeration defining IDs for some classes derived from Operator.
double p(const Vector &x, double t)
PetscBCHandler(Type _type=ZERO)
PetscInt NNZ() const
Returns the number of nonzeros.
PetscLinearSolver(MPI_Comm comm, const std::string &prefix=std::string(), bool wrap=true)
virtual void Mult(const Vector &b, Vector &x) const
Application of the preconditioner.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Mat A
The actual PETSc object.
virtual Operator & GetImplicitGradient(const Vector &x, const Vector &k, double shift) const
Return an Operator representing (dF/dk shift + dF/dx) at the given x, k, and the currently set time...
PetscInt N() const
Returns the global number of columns.
PetscParVector * GetY() const
Returns the inner vector in the range of A (it creates it if needed)
void SetJacobianType(Operator::Type type)
void MakeWrapper(MPI_Comm comm, const Operator *op, Mat *B)
Creates a wrapper around a mfem::Operator op using PETSc's MATSHELL object and returns the Mat in B...
void SetUpdate(void(*update)(Operator *op, int it, const mfem::Vector &F, const mfem::Vector &X, const mfem::Vector &D, const mfem::Vector &P))
bool operatorset
Boolean to handle SetOperator calls.
PetscParVector * X
Auxiliary vectors for typecasting.
void MultTranspose(double a, const Vector &x, double b, Vector &y) const
Matvec transpose: y = a A^T x + b y.
int height
Dimension of the output / number of rows in the matrix.
PetscParVector & operator-=(const PetscParVector &y)
virtual void ImplicitMult(const Vector &x, const Vector &k, Vector &y) const
Perform the action of the implicit part of the operator, F: y = F(x, k, t) where t is the current tim...
virtual ~PetscNonlinearSolver()
virtual ~PetscODESolver()
PetscSolver()
Construct an empty PetscSolver. Initialize protected objects to NULL.
void SetPreconditionerFactory(PetscPreconditionerFactory *factory)
Sets the object for the creation of the preconditioner.
void MFEMInitializePetsc()
Convenience functions to initialize/finalize PETSc.
Mat ReleaseMat(bool dereference)
Release the PETSc Mat object. If dereference is true, decrement the refcount of the Mat object...
PetscParVector(MPI_Comm comm, PetscInt glob_size, PetscInt *col=NULL)
Creates vector with given global size and partitioning of the columns.
virtual void MonitorSolution(PetscInt it, PetscReal norm, const Vector &x)
Monitor the solution vector x.
ID for class PetscParMatrix, MATAIJ format.
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
MPI_Comm GetComm() const
Get the associated MPI communicator.
PetscInt GlobalSize() const
Returns the global number of rows.
PetscInt GetRowStart() const
Returns the global index of the first local row.
struct _p_PetscObject * PetscObject
void SetAbsTol(double tol)
Helper class for handling essential boundary conditions.
PetscParVector * GetX() const
Returns the inner vector in the domain of A (it creates it if needed)
Array< int > & GetTDofs()
Gets essential dofs (local, per-process numbering)
PetscParVector & operator=(PetscScalar d)
Set constant values.
HYPRE_Int * GetTrueDofOffsets() const
virtual void MonitorResidual(PetscInt it, PetscReal norm, const Vector &r)
Monitor the residual vector r.
int NumRowBlocks() const
Return the number of row blocks.
PetscParMatrix * TripleMatrixProduct(PetscParMatrix *R, PetscParMatrix *A, PetscParMatrix *P)
Returns the matrix R * A * P.
Identity Operator I: x -> x.
void PlaceArray(PetscScalar *temp_data)
Temporarily replace the data of the PETSc Vec object. To return to the original data array...
void FreePrivateContext()
TimeDependentOperator * f
Pointer to the associated TimeDependentOperator.
Vector * GlobalVector() const
Returns the global vector in each processor.
PetscODESolver(MPI_Comm comm, const std::string &prefix=std::string())
void EliminateRows(const Array< int > &rows)
Eliminate only the rows from the matrix.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Wrapper for hypre's ParCSR matrix class.
A class to handle Block systems in a matrix-free implementation.
virtual void Mult(const Vector &b, Vector &x) const
Application of the solver.
void operator*=(double s)
Scale all entries by s: A_scaled = s*A.
int NumColBlocks() const
Return the number of column blocks.
void SetTDofs(Array< int > &list)
Sets essential dofs (local, per-process numbering)
ID for class PetscParMatrix, MATIS format.
virtual void MultTranspose(const Vector &b, Vector &x) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
int width
Dimension of the input / number of columns in the matrix.
void * private_ctx
Private context for solver.
void SetUp(PetscInt n)
SetUp the helper object, where n is the size of the solution vector.
void MakeRef(const PetscParMatrix &master)
Makes this object a reference to another PetscParMatrix.
void ScaleCols(const Vector &s)
Scale the local col i by s(i).
double f(const Vector &p)