#include /*I "petscmat.h" I*/ typedef struct _Mat_CompositeLink *Mat_CompositeLink; struct _Mat_CompositeLink { Mat mat; Vec work; Mat_CompositeLink next,prev; }; typedef struct { MatCompositeType type; Mat_CompositeLink head,tail; Vec work; PetscScalar scale; /* scale factor supplied with MatScale() */ Vec left,right; /* left and right diagonal scaling provided with MatDiagonalScale() */ Vec leftwork,rightwork; PetscInt nmat; PetscBool mergefromright; } Mat_Composite; PetscErrorCode MatDestroy_Composite(Mat mat) { PetscErrorCode ierr; Mat_Composite *shell = (Mat_Composite*)mat->data; Mat_CompositeLink next = shell->head,oldnext; PetscFunctionBegin; while (next) { ierr = MatDestroy(&next->mat);CHKERRQ(ierr); if (next->work && (!next->next || next->work != next->next->work)) { ierr = VecDestroy(&next->work);CHKERRQ(ierr); } oldnext = next; next = next->next; ierr = PetscFree(oldnext);CHKERRQ(ierr); } ierr = VecDestroy(&shell->work);CHKERRQ(ierr); ierr = VecDestroy(&shell->left);CHKERRQ(ierr); ierr = VecDestroy(&shell->right);CHKERRQ(ierr); ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr); ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr); ierr = PetscFree(mat->data);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y) { Mat_Composite *shell = (Mat_Composite*)A->data; Mat_CompositeLink next = shell->head; PetscErrorCode ierr; Vec in,out; PetscFunctionBegin; if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); in = x; if (shell->right) { if (!shell->rightwork) { ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); } ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); in = shell->rightwork; } while (next->next) { if (!next->work) { /* should reuse previous work if the same size */ ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr); } out = next->work; ierr = MatMult(next->mat,in,out);CHKERRQ(ierr); in = out; next = next->next; } ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); if (shell->left) { ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); } ierr = VecScale(y,shell->scale);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y) { Mat_Composite *shell = (Mat_Composite*)A->data; Mat_CompositeLink tail = shell->tail; PetscErrorCode ierr; Vec in,out; PetscFunctionBegin; if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); in = x; if (shell->left) { if (!shell->leftwork) { ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); } ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); in = shell->leftwork; } while (tail->prev) { if (!tail->prev->work) { /* should reuse previous work if the same size */ ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr); } out = tail->prev->work; ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr); in = out; tail = tail->prev; } ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr); if (shell->right) { ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); } ierr = VecScale(y,shell->scale);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y) { Mat_Composite *shell = (Mat_Composite*)A->data; Mat_CompositeLink next = shell->head; PetscErrorCode ierr; Vec in; PetscFunctionBegin; if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); in = x; if (shell->right) { if (!shell->rightwork) { ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); } ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); in = shell->rightwork; } ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); while ((next = next->next)) { ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr); } if (shell->left) { ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); } ierr = VecScale(y,shell->scale);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y) { Mat_Composite *shell = (Mat_Composite*)A->data; Mat_CompositeLink next = shell->head; PetscErrorCode ierr; Vec in; PetscFunctionBegin; if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); in = x; if (shell->left) { if (!shell->leftwork) { ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); } ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); in = shell->leftwork; } ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr); while ((next = next->next)) { ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr); } if (shell->right) { ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); } ierr = VecScale(y,shell->scale);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z) { Mat_Composite *shell = (Mat_Composite*)A->data; PetscErrorCode ierr; PetscFunctionBegin; if (y != z) { ierr = MatMult(A,x,z);CHKERRQ(ierr); ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); } else { if (!shell->leftwork) { ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr); } ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr); ierr = VecCopy(y,z);CHKERRQ(ierr); ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr); } PetscFunctionReturn(0); } PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z) { Mat_Composite *shell = (Mat_Composite*)A->data; PetscErrorCode ierr; PetscFunctionBegin; if (y != z) { ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr); ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); } else { if (!shell->rightwork) { ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr); } ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr); ierr = VecCopy(y,z);CHKERRQ(ierr); ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr); } PetscFunctionReturn(0); } PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v) { Mat_Composite *shell = (Mat_Composite*)A->data; Mat_CompositeLink next = shell->head; PetscErrorCode ierr; PetscFunctionBegin; if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling"); ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr); if (next->next && !shell->work) { ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr); } while ((next = next->next)) { ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr); ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr); } ierr = VecScale(v,shell->scale);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t) { PetscErrorCode ierr; PetscBool flg = PETSC_FALSE; PetscFunctionBegin; ierr = PetscOptionsGetBool(((PetscObject)Y)->options,((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = MatCompositeMerge(Y);CHKERRQ(ierr); } PetscFunctionReturn(0); } PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha) { Mat_Composite *a = (Mat_Composite*)inA->data; PetscFunctionBegin; a->scale *= alpha; PetscFunctionReturn(0); } PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right) { Mat_Composite *a = (Mat_Composite*)inA->data; PetscErrorCode ierr; PetscFunctionBegin; if (left) { if (!a->left) { ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); ierr = VecCopy(left,a->left);CHKERRQ(ierr); } else { ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); } } if (right) { if (!a->right) { ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); ierr = VecCopy(right,a->right);CHKERRQ(ierr); } else { ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); } } PetscFunctionReturn(0); } /*@ MatCreateComposite - Creates a matrix as the sum or product of one or more matrices Collective on MPI_Comm Input Parameters: + comm - MPI communicator . nmat - number of matrices to put in - mats - the matrices Output Parameter: . mat - the matrix Level: advanced Notes: Alternative construction $ MatCreate(comm,&mat); $ MatSetSizes(mat,m,n,M,N); $ MatSetType(mat,MATCOMPOSITE); $ MatCompositeAddMat(mat,mats[0]); $ .... $ MatCompositeAddMat(mat,mats[nmat-1]); $ MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); $ MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE @*/ PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat) { PetscErrorCode ierr; PetscInt m,n,M,N,i; PetscFunctionBegin; if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix"); PetscValidPointer(mat,3); ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr); ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr); ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr); ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr); ierr = MatCreate(comm,mat);CHKERRQ(ierr); ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr); for (i=0; idata; Mat_CompositeLink ilink,next = shell->head; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscNewLog(mat,&ilink);CHKERRQ(ierr); ilink->next = 0; ierr = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr); ilink->mat = smat; if (!next) shell->head = ilink; else { while (next->next) { next = next->next; } next->next = ilink; ilink->prev = next; } shell->tail = ilink; shell->nmat += 1; PetscFunctionReturn(0); } /*@ MatCompositeAddMat - Add another matrix to a composite matrix. Collective on Mat Input Parameters: + mat - the composite matrix - smat - the partial matrix Level: advanced .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidHeaderSpecific(smat,MAT_CLASSID,2); ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type) { Mat_Composite *b = (Mat_Composite*)mat->data; PetscFunctionBegin; if (type == MAT_COMPOSITE_MULTIPLICATIVE) { mat->ops->getdiagonal = 0; mat->ops->mult = MatMult_Composite_Multiplicative; mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; b->type = MAT_COMPOSITE_MULTIPLICATIVE; } else { mat->ops->getdiagonal = MatGetDiagonal_Composite; mat->ops->mult = MatMult_Composite; mat->ops->multtranspose = MatMultTranspose_Composite; b->type = MAT_COMPOSITE_ADDITIVE; } PetscFunctionReturn(0); } /*@ MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product. Collective on MPI_Comm Input Parameters: . mat - the composite matrix Level: advanced .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type) { Mat_Composite *b = (Mat_Composite*)mat->data; PetscFunctionBegin; *type = b->type; PetscFunctionReturn(0); } /*@ MatCompositeGetType - Returns type of composite. Not Collective Input Parameter: . mat - the composite matrix Output Parameter: . type - type of composite Level: advanced .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidPointer(type,2); ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeMerge_Composite(Mat mat) { Mat_Composite *shell = (Mat_Composite*)mat->data; Mat_CompositeLink next = shell->head, prev = shell->tail; PetscErrorCode ierr; Mat tmat,newmat; Vec left,right; PetscScalar scale; PetscFunctionBegin; if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); PetscFunctionBegin; if (shell->type == MAT_COMPOSITE_ADDITIVE) { ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); while ((next = next->next)) { ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } } else { if (shell->mergefromright) { ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); while ((next = next->next)) { ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); ierr = MatDestroy(&tmat);CHKERRQ(ierr); tmat = newmat; } } else { ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); while ((prev = prev->prev)) { ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); ierr = MatDestroy(&tmat);CHKERRQ(ierr); tmat = newmat; } } } scale = shell->scale; if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);} if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);} ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr); ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr); ierr = MatScale(mat,scale);CHKERRQ(ierr); ierr = VecDestroy(&left);CHKERRQ(ierr); ierr = VecDestroy(&right);CHKERRQ(ierr); PetscFunctionReturn(0); } /*@ MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix by summing or computing the product of all the matrices inside the composite matrix. Collective on MPI_Comm Input Parameters: . mat - the composite matrix Options Database: . -mat_composite_merge (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked) Level: advanced Notes: The MatType of the resulting matrix will be the same as the MatType of the FIRST matrix in the composite matrix. .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMergeFromRight(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeMerge(Mat mat) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeGetNmat_Composite(Mat mat,PetscInt *nmat) { Mat_Composite *shell = (Mat_Composite*)mat->data; PetscFunctionBegin; *nmat = shell->nmat; PetscFunctionReturn(0); } /*@ MatCompositeGetNmat - Returns the number of matrices in composite. Not Collective Input Parameter: . mat - the composite matrix Output Parameter: . nmat - number of matrices in composite Level: advanced .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeGetNmat(Mat mat,PetscInt *nmat) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidPointer(nmat,2); ierr = PetscUseMethod(mat,"MatCompositeGetNmat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai) { Mat_Composite *shell = (Mat_Composite*)mat->data; Mat_CompositeLink ilink; PetscInt k; PetscFunctionBegin; if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat); ilink = shell->head; for (k=0; knext; } *Ai = ilink->mat; PetscFunctionReturn(0); } /*@ MatCompositeGetMat - Returns the ith matrix from the composite matrix. Logically Collective on Mat Input Parameter: + mat - the composite matrix - i - the number of requested matrix Output Parameter: . Ai - ith matrix in composite Level: advanced .seealso: MatCreateComposite(), MatCompositeGetNmat(), MatCompositeAddMat(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidLogicalCollectiveInt(mat,i,2); PetscValidPointer(Ai,3); ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode MatCompositeSetMergeFromRight_Composite(Mat mat,PetscBool flg) { Mat_Composite *shell = (Mat_Composite*)mat->data; PetscFunctionBegin; shell->mergefromright = flg; PetscFunctionReturn(0); } /*@ MatCompositeSetMergeFromRight - Sets MatCompositeMerge() to start from right. Logically Collective on Mat Input Parameter: + mat - the composite matrix - flg - if true (default) the merge starts with the first added matrix (mat[0]) Level: advanced Notes: Has an effect only if the composite matrix is multiplicative. The resulting matrix is the same regardles of the flg. Only the order of operation is changed. If flg is true the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0]))) otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0]. .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE @*/ PetscErrorCode MatCompositeSetMergeFromRight(Mat mat,PetscBool flg) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidLogicalCollectiveBool(mat,flg,2); ierr = PetscUseMethod(mat,"MatCompositeSetMergeFromRight_C",(Mat,PetscBool),(mat,flg));CHKERRQ(ierr); PetscFunctionReturn(0); } static struct _MatOps MatOps_Values = {0, 0, 0, MatMult_Composite, MatMultAdd_Composite, /* 5*/ MatMultTranspose_Composite, MatMultTransposeAdd_Composite, 0, 0, 0, /* 10*/ 0, 0, 0, 0, 0, /* 15*/ 0, 0, MatGetDiagonal_Composite, MatDiagonalScale_Composite, 0, /* 20*/ 0, MatAssemblyEnd_Composite, 0, 0, /* 24*/ 0, 0, 0, 0, 0, /* 29*/ 0, 0, 0, 0, 0, /* 34*/ 0, 0, 0, 0, 0, /* 39*/ 0, 0, 0, 0, 0, /* 44*/ 0, MatScale_Composite, MatShift_Basic, 0, 0, /* 49*/ 0, 0, 0, 0, 0, /* 54*/ 0, 0, 0, 0, 0, /* 59*/ 0, MatDestroy_Composite, 0, 0, 0, /* 64*/ 0, 0, 0, 0, 0, /* 69*/ 0, 0, 0, 0, 0, /* 74*/ 0, 0, 0, 0, 0, /* 79*/ 0, 0, 0, 0, 0, /* 84*/ 0, 0, 0, 0, 0, /* 89*/ 0, 0, 0, 0, 0, /* 94*/ 0, 0, 0, 0, 0, /*99*/ 0, 0, 0, 0, 0, /*104*/ 0, 0, 0, 0, 0, /*109*/ 0, 0, 0, 0, 0, /*114*/ 0, 0, 0, 0, 0, /*119*/ 0, 0, 0, 0, 0, /*124*/ 0, 0, 0, 0, 0, /*129*/ 0, 0, 0, 0, 0, /*134*/ 0, 0, 0, 0, 0, /*139*/ 0, 0, 0 }; /*MC MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices. The matrices need to have a correct size and parallel layout for the sum or product to be valid. Notes: to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE); Level: advanced .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeMerge(), MatCompositeSetMergeFromRight(), MatCompositeGetNmat(), MatCompositeGetMat() M*/ PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) { Mat_Composite *b; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscNewLog(A,&b);CHKERRQ(ierr); A->data = (void*)b; ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); A->assembled = PETSC_TRUE; A->preallocated = PETSC_TRUE; b->type = MAT_COMPOSITE_ADDITIVE; b->scale = 1.0; b->nmat = 0; b->mergefromright = PETSC_TRUE; ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNmat_C",MatCompositeGetNmat_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeFromRight_C",MatCompositeSetMergeFromRight_Composite);CHKERRQ(ierr); ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr); PetscFunctionReturn(0); }