/*@ MatGetSchurComplement - Obtain the Schur complement from eliminating part of the matrix in another part. Collective on Mat Input Parameters: + A - matrix in which the complement is to be taken . isrow0 - rows to eliminate . iscol0 - columns to eliminate, (isrow0,iscol0) should be square and nonsingular . isrow1 - rows in which the Schur complement is formed . iscol1 - columns in which the Schur complement is formed . mreuse - MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX, use MAT_IGNORE_MATRIX to put nothing in S . plump - the type of approximation used for the inverse of the (0,0) block used in forming Sp: MAT_SCHUR_COMPLEMENT_AINV_DIAG or MAT_SCHUR_COMPLEMENT_AINV_LUMP - preuse - MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX, use MAT_IGNORE_MATRIX to put nothing in Sp Output Parameters: + S - exact Schur complement, often of type MATSCHURCOMPLEMENT which is difficult to use for preconditioning - Sp - approximate Schur complement suitable for preconditioning Note: Since the real Schur complement is usually dense, providing a good approximation to newpmat usually requires application-specific information. The default for assembled matrices is to use the inverse of the diagonal of the (0,0) block A00 in place of A00^{-1}. This rarely produce a scalable algorithm. Optionally, A00 can be lumped before forming inv(diag(A00)). Sometimes users would like to provide problem-specific data in the Schur complement, usually only for special row and column index sets. In that case, the user should call PetscObjectComposeFunction() to set "MatNestGetSubMat_C" to their function. If their function needs to fall back to the default implementation, it should call MatGetSchurComplement_Basic(). Level: advanced Concepts: matrices^submatrices .seealso: MatGetSubMatrix(), PCFIELDSPLIT, MatCreateSchurComplement(), MatSchurComplementAinvType @*/ PetscErrorCode MatGetSchurComplement(Mat A,IS isrow0,IS iscol0,IS isrow1,IS iscol1,MatReuse mreuse,Mat *S,MatSchurComplementAinvType ainvtype,MatReuse preuse,Mat *Sp) { PetscErrorCode ierr,(*f)(Mat,IS,IS,IS,IS,MatReuse,Mat*,MatReuse,Mat*) = NULL; PetscFunctionBegin; PetscValidHeaderSpecific(A,MAT_CLASSID,1); PetscValidHeaderSpecific(isrow0,IS_CLASSID,2); PetscValidHeaderSpecific(iscol0,IS_CLASSID,3); PetscValidHeaderSpecific(isrow1,IS_CLASSID,4); PetscValidHeaderSpecific(iscol1,IS_CLASSID,5); if (mreuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*S,MAT_CLASSID,7); if (preuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*Sp,MAT_CLASSID,9); PetscValidType(A,1); if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); f = NULL; if (mreuse == MAT_REUSE_MATRIX) { /* This is the only situation, in which we can demand that the user pass a non-NULL pointer to non-garbage in S. */ ierr = PetscObjectQueryFunction((PetscObject)*S,"MatGetSchurComplement_C",&f);CHKERRQ(ierr); } if (f) { ierr = (*f)(A,isrow0,iscol0,isrow1,iscol1,mreuse,S,preuse,Sp);CHKERRQ(ierr); } else { ierr = MatGetSchurComplement_Basic(A,isrow0,iscol0,isrow1,iscol1,mreuse,S,ainvtype,preuse,Sp);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ MatGetSchurComplement - Obtain the Schur complement from eliminating part of the matrix in another part. Collective on Mat Input Parameters: + mat - Matrix in which the complement is to be taken . isrow0 - rows to eliminate . iscol0 - columns to eliminate, (isrow0,iscol0) should be square and nonsingular . isrow1 - rows in which the Schur complement is formed . iscol1 - columns in which the Schur complement is formed . mreuse - MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX, use MAT_IGNORE_MATRIX to put nothing in newmat - preuse - MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX, use MAT_IGNORE_MATRIX to put nothing in newpmat Output Parameters: + newmat - exact Schur complement, often of type MATSCHURCOMPLEMENT which is difficult to use for preconditioning - newpmat - approximate Schur complement suitable for preconditioning Note: Since the real Schur complement is usually dense, providing a good approximation to newpmat usually requires application-specific information. The default for assembled matrices is to use the diagonal of the (0,0) block which will rarely produce a scalable algorithm. Sometimes users would like to provide problem-specific data in the Schur complement, usually only for special row and column index sets. In that case, the user should call PetscObjectComposeFunctionDynamic() to set "MatNestGetSubMat_C" to their function. If their function needs to fall back to the default implementation, it should call MatGetSchurComplement_Basic(). Level: advanced Concepts: matrices^submatrices .seealso: MatGetSubMatrix(), PCFIELDSPLIT, MatCreateSchurComplement() @*/ PetscErrorCode MatGetSchurComplement(Mat mat,IS isrow0,IS iscol0,IS isrow1,IS iscol1,MatReuse mreuse,Mat *newmat,MatReuse preuse,Mat *newpmat) { PetscErrorCode ierr,(*f)(Mat,IS,IS,IS,IS,MatReuse,Mat*,MatReuse,Mat*); PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidHeaderSpecific(isrow0,IS_CLASSID,2); PetscValidHeaderSpecific(iscol0,IS_CLASSID,3); PetscValidHeaderSpecific(isrow1,IS_CLASSID,4); PetscValidHeaderSpecific(iscol1,IS_CLASSID,5); if (mreuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,7); if (preuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newpmat,MAT_CLASSID,9); PetscValidType(mat,1); if (mat->factortype) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); ierr = PetscObjectQueryFunction((PetscObject)mat,"MatGetSchurComplement_C",(void(**)(void))&f);CHKERRQ(ierr); if (f) { ierr = (*f)(mat,isrow0,iscol0,isrow1,iscol1,mreuse,newmat,preuse,newpmat);CHKERRQ(ierr); } else { ierr = MatGetSchurComplement_Basic(mat,isrow0,iscol0,isrow1,iscol1,mreuse,newmat,preuse,newpmat);CHKERRQ(ierr); } PetscFunctionReturn(0); }