1793850ffSBarry Smith 2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 3793850ffSBarry Smith 4793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink; 5793850ffSBarry Smith struct _Mat_CompositeLink { 6793850ffSBarry Smith Mat mat; 76d7c1e57SBarry Smith Vec work; 86d7c1e57SBarry Smith Mat_CompositeLink next,prev; 9793850ffSBarry Smith }; 10793850ffSBarry Smith 11793850ffSBarry Smith typedef struct { 126d7c1e57SBarry Smith MatCompositeType type; 136d7c1e57SBarry Smith Mat_CompositeLink head,tail; 14793850ffSBarry Smith Vec work; 15e4fc5df0SBarry Smith PetscScalar scale; /* scale factor supplied with MatScale() */ 16e4fc5df0SBarry Smith Vec left,right; /* left and right diagonal scaling provided with MatDiagonalScale() */ 17e4fc5df0SBarry Smith Vec leftwork,rightwork; 186a7ede75SJakub Kruzik PetscInt nmat; 19*4b2558d6SJakub Kruzik PetscBool merge; 2004d534ceSJakub Kruzik PetscBool mergefromright; 21793850ffSBarry Smith } Mat_Composite; 22793850ffSBarry Smith 23793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat) 24793850ffSBarry Smith { 25793850ffSBarry Smith PetscErrorCode ierr; 262c33bbaeSSatish Balay Mat_Composite *shell = (Mat_Composite*)mat->data; 276d7c1e57SBarry Smith Mat_CompositeLink next = shell->head,oldnext; 28793850ffSBarry Smith 29793850ffSBarry Smith PetscFunctionBegin; 30793850ffSBarry Smith while (next) { 316bf464f9SBarry Smith ierr = MatDestroy(&next->mat);CHKERRQ(ierr); 326d7c1e57SBarry Smith if (next->work && (!next->next || next->work != next->next->work)) { 336bf464f9SBarry Smith ierr = VecDestroy(&next->work);CHKERRQ(ierr); 346d7c1e57SBarry Smith } 356d7c1e57SBarry Smith oldnext = next; 36793850ffSBarry Smith next = next->next; 376d7c1e57SBarry Smith ierr = PetscFree(oldnext);CHKERRQ(ierr); 38793850ffSBarry Smith } 396bf464f9SBarry Smith ierr = VecDestroy(&shell->work);CHKERRQ(ierr); 406bf464f9SBarry Smith ierr = VecDestroy(&shell->left);CHKERRQ(ierr); 416bf464f9SBarry Smith ierr = VecDestroy(&shell->right);CHKERRQ(ierr); 426bf464f9SBarry Smith ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr); 436bf464f9SBarry Smith ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr); 446bf464f9SBarry Smith ierr = PetscFree(mat->data);CHKERRQ(ierr); 45793850ffSBarry Smith PetscFunctionReturn(0); 46793850ffSBarry Smith } 47793850ffSBarry Smith 486d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y) 496d7c1e57SBarry Smith { 506d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 516d7c1e57SBarry Smith Mat_CompositeLink next = shell->head; 526d7c1e57SBarry Smith PetscErrorCode ierr; 536d7c1e57SBarry Smith Vec in,out; 546d7c1e57SBarry Smith 556d7c1e57SBarry Smith PetscFunctionBegin; 56e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 576d7c1e57SBarry Smith in = x; 58e4fc5df0SBarry Smith if (shell->right) { 59e4fc5df0SBarry Smith if (!shell->rightwork) { 60e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 61e4fc5df0SBarry Smith } 62e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 63e4fc5df0SBarry Smith in = shell->rightwork; 64e4fc5df0SBarry Smith } 656d7c1e57SBarry Smith while (next->next) { 666d7c1e57SBarry Smith if (!next->work) { /* should reuse previous work if the same size */ 672a7a6963SBarry Smith ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr); 686d7c1e57SBarry Smith } 696d7c1e57SBarry Smith out = next->work; 706d7c1e57SBarry Smith ierr = MatMult(next->mat,in,out);CHKERRQ(ierr); 716d7c1e57SBarry Smith in = out; 726d7c1e57SBarry Smith next = next->next; 736d7c1e57SBarry Smith } 746d7c1e57SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 75e4fc5df0SBarry Smith if (shell->left) { 76e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 77e4fc5df0SBarry Smith } 78e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 796d7c1e57SBarry Smith PetscFunctionReturn(0); 806d7c1e57SBarry Smith } 816d7c1e57SBarry Smith 826d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y) 836d7c1e57SBarry Smith { 846d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 856d7c1e57SBarry Smith Mat_CompositeLink tail = shell->tail; 866d7c1e57SBarry Smith PetscErrorCode ierr; 876d7c1e57SBarry Smith Vec in,out; 886d7c1e57SBarry Smith 896d7c1e57SBarry Smith PetscFunctionBegin; 90e32f2f54SBarry Smith if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 916d7c1e57SBarry Smith in = x; 92e4fc5df0SBarry Smith if (shell->left) { 93e4fc5df0SBarry Smith if (!shell->leftwork) { 94e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 95e4fc5df0SBarry Smith } 96e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 97e4fc5df0SBarry Smith in = shell->leftwork; 98e4fc5df0SBarry Smith } 996d7c1e57SBarry Smith while (tail->prev) { 1006d7c1e57SBarry Smith if (!tail->prev->work) { /* should reuse previous work if the same size */ 1012a7a6963SBarry Smith ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr); 1026d7c1e57SBarry Smith } 1036d7c1e57SBarry Smith out = tail->prev->work; 1046d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr); 1056d7c1e57SBarry Smith in = out; 1066d7c1e57SBarry Smith tail = tail->prev; 1076d7c1e57SBarry Smith } 1086d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr); 109e4fc5df0SBarry Smith if (shell->right) { 110e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 111e4fc5df0SBarry Smith } 112e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 1136d7c1e57SBarry Smith PetscFunctionReturn(0); 1146d7c1e57SBarry Smith } 1156d7c1e57SBarry Smith 116793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y) 117793850ffSBarry Smith { 118793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 119793850ffSBarry Smith Mat_CompositeLink next = shell->head; 120793850ffSBarry Smith PetscErrorCode ierr; 121e4fc5df0SBarry Smith Vec in; 122793850ffSBarry Smith 123793850ffSBarry Smith PetscFunctionBegin; 124e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 125e4fc5df0SBarry Smith in = x; 126e4fc5df0SBarry Smith if (shell->right) { 127e4fc5df0SBarry Smith if (!shell->rightwork) { 128e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 129793850ffSBarry Smith } 130e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 131e4fc5df0SBarry Smith in = shell->rightwork; 132e4fc5df0SBarry Smith } 133e4fc5df0SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 134e4fc5df0SBarry Smith while ((next = next->next)) { 135e4fc5df0SBarry Smith ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr); 136e4fc5df0SBarry Smith } 137e4fc5df0SBarry Smith if (shell->left) { 138e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 139e4fc5df0SBarry Smith } 140e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 141793850ffSBarry Smith PetscFunctionReturn(0); 142793850ffSBarry Smith } 143793850ffSBarry Smith 144793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y) 145793850ffSBarry Smith { 146793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 147793850ffSBarry Smith Mat_CompositeLink next = shell->head; 148793850ffSBarry Smith PetscErrorCode ierr; 149e4fc5df0SBarry Smith Vec in; 150793850ffSBarry Smith 151793850ffSBarry Smith PetscFunctionBegin; 152e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 153e4fc5df0SBarry Smith in = x; 154e4fc5df0SBarry Smith if (shell->left) { 155e4fc5df0SBarry Smith if (!shell->leftwork) { 156e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 157793850ffSBarry Smith } 158e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 159e4fc5df0SBarry Smith in = shell->leftwork; 160e4fc5df0SBarry Smith } 161e4fc5df0SBarry Smith ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr); 162e4fc5df0SBarry Smith while ((next = next->next)) { 163e4fc5df0SBarry Smith ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr); 164e4fc5df0SBarry Smith } 165e4fc5df0SBarry Smith if (shell->right) { 166e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 167e4fc5df0SBarry Smith } 168e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 169793850ffSBarry Smith PetscFunctionReturn(0); 170793850ffSBarry Smith } 171793850ffSBarry Smith 1727bf3a71bSJakub Kruzik PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z) 1737bf3a71bSJakub Kruzik { 1747bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)A->data; 1757bf3a71bSJakub Kruzik PetscErrorCode ierr; 1767bf3a71bSJakub Kruzik 1777bf3a71bSJakub Kruzik PetscFunctionBegin; 1787bf3a71bSJakub Kruzik if (y != z) { 1797bf3a71bSJakub Kruzik ierr = MatMult(A,x,z);CHKERRQ(ierr); 1807bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); 1817bf3a71bSJakub Kruzik } else { 1827bf3a71bSJakub Kruzik if (!shell->leftwork) { 1837bf3a71bSJakub Kruzik ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr); 1847bf3a71bSJakub Kruzik } 1857bf3a71bSJakub Kruzik ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr); 1867bf3a71bSJakub Kruzik ierr = VecCopy(y,z);CHKERRQ(ierr); 1877bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr); 1887bf3a71bSJakub Kruzik } 1897bf3a71bSJakub Kruzik PetscFunctionReturn(0); 1907bf3a71bSJakub Kruzik } 1917bf3a71bSJakub Kruzik 1927bf3a71bSJakub Kruzik PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z) 1937bf3a71bSJakub Kruzik { 1947bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)A->data; 1957bf3a71bSJakub Kruzik PetscErrorCode ierr; 1967bf3a71bSJakub Kruzik 1977bf3a71bSJakub Kruzik PetscFunctionBegin; 1987bf3a71bSJakub Kruzik if (y != z) { 1997bf3a71bSJakub Kruzik ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr); 2007bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); 2017bf3a71bSJakub Kruzik } else { 2027bf3a71bSJakub Kruzik if (!shell->rightwork) { 2037bf3a71bSJakub Kruzik ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr); 2047bf3a71bSJakub Kruzik } 2057bf3a71bSJakub Kruzik ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr); 2067bf3a71bSJakub Kruzik ierr = VecCopy(y,z);CHKERRQ(ierr); 2077bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr); 2087bf3a71bSJakub Kruzik } 2097bf3a71bSJakub Kruzik PetscFunctionReturn(0); 2107bf3a71bSJakub Kruzik } 2117bf3a71bSJakub Kruzik 212793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v) 213793850ffSBarry Smith { 214793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 215793850ffSBarry Smith Mat_CompositeLink next = shell->head; 216793850ffSBarry Smith PetscErrorCode ierr; 217793850ffSBarry Smith 218793850ffSBarry Smith PetscFunctionBegin; 219e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 220e32f2f54SBarry Smith if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling"); 221e4fc5df0SBarry Smith 222793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr); 223793850ffSBarry Smith if (next->next && !shell->work) { 224793850ffSBarry Smith ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr); 225793850ffSBarry Smith } 226793850ffSBarry Smith while ((next = next->next)) { 227793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr); 228793850ffSBarry Smith ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr); 229793850ffSBarry Smith } 230e4fc5df0SBarry Smith ierr = VecScale(v,shell->scale);CHKERRQ(ierr); 231793850ffSBarry Smith PetscFunctionReturn(0); 232793850ffSBarry Smith } 233793850ffSBarry Smith 234793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t) 235793850ffSBarry Smith { 236*4b2558d6SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)Y->data; 237b52f573bSBarry Smith PetscErrorCode ierr; 238b52f573bSBarry Smith 239793850ffSBarry Smith PetscFunctionBegin; 240*4b2558d6SJakub Kruzik if (shell->merge) { 241b52f573bSBarry Smith ierr = MatCompositeMerge(Y);CHKERRQ(ierr); 242b52f573bSBarry Smith } 243793850ffSBarry Smith PetscFunctionReturn(0); 244793850ffSBarry Smith } 245793850ffSBarry Smith 246e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha) 247e4fc5df0SBarry Smith { 248e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 249e4fc5df0SBarry Smith 250e4fc5df0SBarry Smith PetscFunctionBegin; 251321429dbSBarry Smith a->scale *= alpha; 252e4fc5df0SBarry Smith PetscFunctionReturn(0); 253e4fc5df0SBarry Smith } 254e4fc5df0SBarry Smith 255e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right) 256e4fc5df0SBarry Smith { 257e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 258e4fc5df0SBarry Smith PetscErrorCode ierr; 259e4fc5df0SBarry Smith 260e4fc5df0SBarry Smith PetscFunctionBegin; 261e4fc5df0SBarry Smith if (left) { 262321429dbSBarry Smith if (!a->left) { 263e4fc5df0SBarry Smith ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); 264e4fc5df0SBarry Smith ierr = VecCopy(left,a->left);CHKERRQ(ierr); 265321429dbSBarry Smith } else { 266321429dbSBarry Smith ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); 267321429dbSBarry Smith } 268e4fc5df0SBarry Smith } 269e4fc5df0SBarry Smith if (right) { 270321429dbSBarry Smith if (!a->right) { 271e4fc5df0SBarry Smith ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); 272e4fc5df0SBarry Smith ierr = VecCopy(right,a->right);CHKERRQ(ierr); 273321429dbSBarry Smith } else { 274321429dbSBarry Smith ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); 275321429dbSBarry Smith } 276e4fc5df0SBarry Smith } 277e4fc5df0SBarry Smith PetscFunctionReturn(0); 278e4fc5df0SBarry Smith } 279793850ffSBarry Smith 280*4b2558d6SJakub Kruzik PetscErrorCode MatSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,Mat A) 281*4b2558d6SJakub Kruzik { 282*4b2558d6SJakub Kruzik Mat_Composite *a = (Mat_Composite*)A->data; 283*4b2558d6SJakub Kruzik PetscErrorCode ierr; 284*4b2558d6SJakub Kruzik 285*4b2558d6SJakub Kruzik PetscFunctionBegin; 286*4b2558d6SJakub Kruzik ierr = PetscOptionsHead(PetscOptionsObject,"MATCOMPOSITE options");CHKERRQ(ierr); 287*4b2558d6SJakub Kruzik ierr = PetscOptionsBool("-mat_composite_merge","Merge at MatAssemblyEnd","MatCompositeMerge",a->merge,&a->merge,NULL);CHKERRQ(ierr); 288*4b2558d6SJakub Kruzik ierr = PetscOptionsBool("-mat_composite_merge_from_right","Set direction of merge","MatCompositeSetMergeFromRight",a->mergefromright,&a->mergefromright,NULL);CHKERRQ(ierr); 289*4b2558d6SJakub Kruzik ierr = PetscOptionsTail();CHKERRQ(ierr); 290*4b2558d6SJakub Kruzik PetscFunctionReturn(0); 291*4b2558d6SJakub Kruzik } 292*4b2558d6SJakub Kruzik 2932c0821f3SBarry Smith /*@ 2948bd739bdSJakub Kruzik MatCreateComposite - Creates a matrix as the sum or product of one or more matrices 295793850ffSBarry Smith 296793850ffSBarry Smith Collective on MPI_Comm 297793850ffSBarry Smith 298793850ffSBarry Smith Input Parameters: 299793850ffSBarry Smith + comm - MPI communicator 300793850ffSBarry Smith . nmat - number of matrices to put in 301793850ffSBarry Smith - mats - the matrices 302793850ffSBarry Smith 303793850ffSBarry Smith Output Parameter: 304db36af27SMatthew G. Knepley . mat - the matrix 305793850ffSBarry Smith 306*4b2558d6SJakub Kruzik Options Database Keys: 307*4b2558d6SJakub Kruzik + -mat_composite_merge - merge in MatAssemblyEnd() 308*4b2558d6SJakub Kruzik - -mat_composite_merge_from_right - merge starts from right 309*4b2558d6SJakub Kruzik 310793850ffSBarry Smith Level: advanced 311793850ffSBarry Smith 312793850ffSBarry Smith Notes: 313793850ffSBarry Smith Alternative construction 314793850ffSBarry Smith $ MatCreate(comm,&mat); 315793850ffSBarry Smith $ MatSetSizes(mat,m,n,M,N); 316793850ffSBarry Smith $ MatSetType(mat,MATCOMPOSITE); 317793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[0]); 318793850ffSBarry Smith $ .... 319793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[nmat-1]); 320b52f573bSBarry Smith $ MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); 321b52f573bSBarry Smith $ MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); 322793850ffSBarry Smith 3236d7c1e57SBarry Smith For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] 3246d7c1e57SBarry Smith 3256dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE 326793850ffSBarry Smith 327793850ffSBarry Smith @*/ 3287087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat) 329793850ffSBarry Smith { 330793850ffSBarry Smith PetscErrorCode ierr; 331793850ffSBarry Smith PetscInt m,n,M,N,i; 332793850ffSBarry Smith 333793850ffSBarry Smith PetscFunctionBegin; 334e32f2f54SBarry Smith if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix"); 335f3f84630SBarry Smith PetscValidPointer(mat,3); 336793850ffSBarry Smith 337c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr); 338c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr); 339c4f13f43SJakub Kruzik ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr); 340c4f13f43SJakub Kruzik ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr); 341793850ffSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 342793850ffSBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 343793850ffSBarry Smith ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr); 344793850ffSBarry Smith for (i=0; i<nmat; i++) { 345793850ffSBarry Smith ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr); 346793850ffSBarry Smith } 347b52f573bSBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 348b52f573bSBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 349793850ffSBarry Smith PetscFunctionReturn(0); 350793850ffSBarry Smith } 351793850ffSBarry Smith 352d7f81bf2SJakub Kruzik 353d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat) 354d7f81bf2SJakub Kruzik { 355d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 356d7f81bf2SJakub Kruzik Mat_CompositeLink ilink,next = shell->head; 357d7f81bf2SJakub Kruzik PetscErrorCode ierr; 358d7f81bf2SJakub Kruzik 359d7f81bf2SJakub Kruzik PetscFunctionBegin; 360d7f81bf2SJakub Kruzik ierr = PetscNewLog(mat,&ilink);CHKERRQ(ierr); 361d7f81bf2SJakub Kruzik ilink->next = 0; 362d7f81bf2SJakub Kruzik ierr = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr); 363d7f81bf2SJakub Kruzik ilink->mat = smat; 364d7f81bf2SJakub Kruzik 365d7f81bf2SJakub Kruzik if (!next) shell->head = ilink; 366d7f81bf2SJakub Kruzik else { 367d7f81bf2SJakub Kruzik while (next->next) { 368d7f81bf2SJakub Kruzik next = next->next; 369d7f81bf2SJakub Kruzik } 370d7f81bf2SJakub Kruzik next->next = ilink; 371d7f81bf2SJakub Kruzik ilink->prev = next; 372d7f81bf2SJakub Kruzik } 373d7f81bf2SJakub Kruzik shell->tail = ilink; 374d7f81bf2SJakub Kruzik shell->nmat += 1; 375d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 376d7f81bf2SJakub Kruzik } 377d7f81bf2SJakub Kruzik 378793850ffSBarry Smith /*@ 3798bd739bdSJakub Kruzik MatCompositeAddMat - Add another matrix to a composite matrix. 380793850ffSBarry Smith 381793850ffSBarry Smith Collective on Mat 382793850ffSBarry Smith 383793850ffSBarry Smith Input Parameters: 384793850ffSBarry Smith + mat - the composite matrix 385793850ffSBarry Smith - smat - the partial matrix 386793850ffSBarry Smith 387793850ffSBarry Smith Level: advanced 388793850ffSBarry Smith 3898bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE 390793850ffSBarry Smith @*/ 3917087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat) 392793850ffSBarry Smith { 393793850ffSBarry Smith PetscErrorCode ierr; 394793850ffSBarry Smith 395793850ffSBarry Smith PetscFunctionBegin; 3960700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3970700a824SBarry Smith PetscValidHeaderSpecific(smat,MAT_CLASSID,2); 398d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr); 399d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 400d7f81bf2SJakub Kruzik } 401793850ffSBarry Smith 402d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type) 403d7f81bf2SJakub Kruzik { 404d7f81bf2SJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 405d7f81bf2SJakub Kruzik 406d7f81bf2SJakub Kruzik PetscFunctionBegin; 407ced1ac25SJakub Kruzik b->type = type; 408d7f81bf2SJakub Kruzik if (type == MAT_COMPOSITE_MULTIPLICATIVE) { 409d7f81bf2SJakub Kruzik mat->ops->getdiagonal = 0; 410d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite_Multiplicative; 411d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; 412d7f81bf2SJakub Kruzik } else { 413d7f81bf2SJakub Kruzik mat->ops->getdiagonal = MatGetDiagonal_Composite; 414d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite; 415d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite; 416793850ffSBarry Smith } 4176d7c1e57SBarry Smith PetscFunctionReturn(0); 4186d7c1e57SBarry Smith } 4196d7c1e57SBarry Smith 4202c0821f3SBarry Smith /*@ 4218bd739bdSJakub Kruzik MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product. 4226d7c1e57SBarry Smith 4236d7c1e57SBarry Smith Collective on MPI_Comm 4246d7c1e57SBarry Smith 4256d7c1e57SBarry Smith Input Parameters: 4266d7c1e57SBarry Smith . mat - the composite matrix 4276d7c1e57SBarry Smith 4286d7c1e57SBarry Smith Level: advanced 4296d7c1e57SBarry Smith 4306dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE 4316d7c1e57SBarry Smith 4326d7c1e57SBarry Smith @*/ 4337087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type) 4346d7c1e57SBarry Smith { 4356d7c1e57SBarry Smith PetscErrorCode ierr; 4366d7c1e57SBarry Smith 4376d7c1e57SBarry Smith PetscFunctionBegin; 438d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 439d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr); 440793850ffSBarry Smith PetscFunctionReturn(0); 441793850ffSBarry Smith } 442793850ffSBarry Smith 4436dbc55e5SJakub Kruzik static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type) 4446dbc55e5SJakub Kruzik { 4456dbc55e5SJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 4466dbc55e5SJakub Kruzik 4476dbc55e5SJakub Kruzik PetscFunctionBegin; 4486dbc55e5SJakub Kruzik *type = b->type; 4496dbc55e5SJakub Kruzik PetscFunctionReturn(0); 4506dbc55e5SJakub Kruzik } 4516dbc55e5SJakub Kruzik 4526dbc55e5SJakub Kruzik /*@ 4536dbc55e5SJakub Kruzik MatCompositeGetType - Returns type of composite. 4546dbc55e5SJakub Kruzik 4556dbc55e5SJakub Kruzik Not Collective 4566dbc55e5SJakub Kruzik 4576dbc55e5SJakub Kruzik Input Parameter: 4586dbc55e5SJakub Kruzik . mat - the composite matrix 4596dbc55e5SJakub Kruzik 4606dbc55e5SJakub Kruzik Output Parameter: 4616dbc55e5SJakub Kruzik . type - type of composite 4626dbc55e5SJakub Kruzik 4636dbc55e5SJakub Kruzik Level: advanced 4646dbc55e5SJakub Kruzik 4656dbc55e5SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE 4666dbc55e5SJakub Kruzik 4676dbc55e5SJakub Kruzik @*/ 4686dbc55e5SJakub Kruzik PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type) 4696dbc55e5SJakub Kruzik { 4706dbc55e5SJakub Kruzik PetscErrorCode ierr; 4716dbc55e5SJakub Kruzik 4726dbc55e5SJakub Kruzik PetscFunctionBegin; 4736dbc55e5SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 4746dbc55e5SJakub Kruzik PetscValidPointer(type,2); 4756dbc55e5SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr); 4766dbc55e5SJakub Kruzik PetscFunctionReturn(0); 4776dbc55e5SJakub Kruzik } 4786dbc55e5SJakub Kruzik 479d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat) 480b52f573bSBarry Smith { 481b52f573bSBarry Smith Mat_Composite *shell = (Mat_Composite*)mat->data; 4826d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, prev = shell->tail; 483b52f573bSBarry Smith PetscErrorCode ierr; 4846d7c1e57SBarry Smith Mat tmat,newmat; 4851ba60692SJed Brown Vec left,right; 4861ba60692SJed Brown PetscScalar scale; 487b52f573bSBarry Smith 488b52f573bSBarry Smith PetscFunctionBegin; 489e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 490b52f573bSBarry Smith 491b52f573bSBarry Smith PetscFunctionBegin; 4926d7c1e57SBarry Smith if (shell->type == MAT_COMPOSITE_ADDITIVE) { 493b52f573bSBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 494b52f573bSBarry Smith while ((next = next->next)) { 495b52f573bSBarry Smith ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 496b52f573bSBarry Smith } 4976d7c1e57SBarry Smith } else { 49804d534ceSJakub Kruzik if (shell->mergefromright) { 4996d7c1e57SBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 500b6cfcaf5SJakub Kruzik while ((next = next->next)) { 501b6cfcaf5SJakub Kruzik ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 5026bf464f9SBarry Smith ierr = MatDestroy(&tmat);CHKERRQ(ierr); 5036d7c1e57SBarry Smith tmat = newmat; 5046d7c1e57SBarry Smith } 50504d534ceSJakub Kruzik } else { 50604d534ceSJakub Kruzik ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 50704d534ceSJakub Kruzik while ((prev = prev->prev)) { 50804d534ceSJakub Kruzik ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 50904d534ceSJakub Kruzik ierr = MatDestroy(&tmat);CHKERRQ(ierr); 51004d534ceSJakub Kruzik tmat = newmat; 51104d534ceSJakub Kruzik } 51204d534ceSJakub Kruzik } 5136d7c1e57SBarry Smith } 5141ba60692SJed Brown 5151ba60692SJed Brown scale = shell->scale; 5161ba60692SJed Brown if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);} 5171ba60692SJed Brown if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);} 5181ba60692SJed Brown 51928be2f97SBarry Smith ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr); 5201ba60692SJed Brown 5211ba60692SJed Brown ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr); 5221ba60692SJed Brown ierr = MatScale(mat,scale);CHKERRQ(ierr); 5231ba60692SJed Brown ierr = VecDestroy(&left);CHKERRQ(ierr); 5241ba60692SJed Brown ierr = VecDestroy(&right);CHKERRQ(ierr); 525b52f573bSBarry Smith PetscFunctionReturn(0); 526b52f573bSBarry Smith } 5276a7ede75SJakub Kruzik 5286a7ede75SJakub Kruzik /*@ 529d7f81bf2SJakub Kruzik MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix 5308bd739bdSJakub Kruzik by summing or computing the product of all the matrices inside the composite matrix. 531d7f81bf2SJakub Kruzik 532d7f81bf2SJakub Kruzik Collective on MPI_Comm 533d7f81bf2SJakub Kruzik 534d7f81bf2SJakub Kruzik Input Parameters: 535d7f81bf2SJakub Kruzik . mat - the composite matrix 536d7f81bf2SJakub Kruzik 537d7f81bf2SJakub Kruzik 538*4b2558d6SJakub Kruzik Options Database Keys: 539*4b2558d6SJakub Kruzik . -mat_composite_merge - merge in MatAssemblyEnd() 540d7f81bf2SJakub Kruzik 541d7f81bf2SJakub Kruzik Level: advanced 542d7f81bf2SJakub Kruzik 543d7f81bf2SJakub Kruzik Notes: 544d7f81bf2SJakub Kruzik The MatType of the resulting matrix will be the same as the MatType of the FIRST 545d7f81bf2SJakub Kruzik matrix in the composite matrix. 546d7f81bf2SJakub Kruzik 54704d534ceSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMergeFromRight(), MATCOMPOSITE 548d7f81bf2SJakub Kruzik 549d7f81bf2SJakub Kruzik @*/ 550d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat) 551d7f81bf2SJakub Kruzik { 552d7f81bf2SJakub Kruzik PetscErrorCode ierr; 553d7f81bf2SJakub Kruzik 554d7f81bf2SJakub Kruzik PetscFunctionBegin; 555d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 556d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr); 557d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 558d7f81bf2SJakub Kruzik } 559d7f81bf2SJakub Kruzik 5606d0add67SJakub Kruzik static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat,PetscInt *nmat) 561d7f81bf2SJakub Kruzik { 562d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 563d7f81bf2SJakub Kruzik 564d7f81bf2SJakub Kruzik PetscFunctionBegin; 565d7f81bf2SJakub Kruzik *nmat = shell->nmat; 566d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 567d7f81bf2SJakub Kruzik } 568d7f81bf2SJakub Kruzik 569d7f81bf2SJakub Kruzik /*@ 5706d0add67SJakub Kruzik MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix. 5716a7ede75SJakub Kruzik 5726a7ede75SJakub Kruzik Not Collective 5736a7ede75SJakub Kruzik 5746a7ede75SJakub Kruzik Input Parameter: 575d7f81bf2SJakub Kruzik . mat - the composite matrix 5766a7ede75SJakub Kruzik 5776a7ede75SJakub Kruzik Output Parameter: 5786d0add67SJakub Kruzik . nmat - number of matrices in the composite matrix 5796a7ede75SJakub Kruzik 5808b5c3584SJakub Kruzik Level: advanced 5816a7ede75SJakub Kruzik 5828bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE 5836a7ede75SJakub Kruzik 5846a7ede75SJakub Kruzik @*/ 5856d0add67SJakub Kruzik PetscErrorCode MatCompositeGetNumberMat(Mat mat,PetscInt *nmat) 5866a7ede75SJakub Kruzik { 587d7f81bf2SJakub Kruzik PetscErrorCode ierr; 5886a7ede75SJakub Kruzik 5896a7ede75SJakub Kruzik PetscFunctionBegin; 590d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 5916a7ede75SJakub Kruzik PetscValidPointer(nmat,2); 5926d0add67SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetNumberMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr); 593d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 594d7f81bf2SJakub Kruzik } 595d7f81bf2SJakub Kruzik 596d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai) 597d7f81bf2SJakub Kruzik { 598d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 599d7f81bf2SJakub Kruzik Mat_CompositeLink ilink; 600d7f81bf2SJakub Kruzik PetscInt k; 601d7f81bf2SJakub Kruzik 602d7f81bf2SJakub Kruzik PetscFunctionBegin; 603d7f81bf2SJakub Kruzik if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat); 604d7f81bf2SJakub Kruzik ilink = shell->head; 605d7f81bf2SJakub Kruzik for (k=0; k<i; k++) { 606d7f81bf2SJakub Kruzik ilink = ilink->next; 607d7f81bf2SJakub Kruzik } 608d7f81bf2SJakub Kruzik *Ai = ilink->mat; 6096a7ede75SJakub Kruzik PetscFunctionReturn(0); 6106a7ede75SJakub Kruzik } 6116a7ede75SJakub Kruzik 6128b5c3584SJakub Kruzik /*@ 6138bd739bdSJakub Kruzik MatCompositeGetMat - Returns the ith matrix from the composite matrix. 6148b5c3584SJakub Kruzik 6158b5c3584SJakub Kruzik Logically Collective on Mat 6168b5c3584SJakub Kruzik 6178b5c3584SJakub Kruzik Input Parameter: 618d7f81bf2SJakub Kruzik + mat - the composite matrix 6198b5c3584SJakub Kruzik - i - the number of requested matrix 6208b5c3584SJakub Kruzik 6218b5c3584SJakub Kruzik Output Parameter: 6228b5c3584SJakub Kruzik . Ai - ith matrix in composite 6238b5c3584SJakub Kruzik 6248b5c3584SJakub Kruzik Level: advanced 6258b5c3584SJakub Kruzik 6266d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNumberMat(), MatCompositeAddMat(), MATCOMPOSITE 6278b5c3584SJakub Kruzik 6288b5c3584SJakub Kruzik @*/ 629d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai) 6308b5c3584SJakub Kruzik { 631d7f81bf2SJakub Kruzik PetscErrorCode ierr; 6328b5c3584SJakub Kruzik 6338b5c3584SJakub Kruzik PetscFunctionBegin; 634d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 635d7f81bf2SJakub Kruzik PetscValidLogicalCollectiveInt(mat,i,2); 6368b5c3584SJakub Kruzik PetscValidPointer(Ai,3); 637d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr); 6388b5c3584SJakub Kruzik PetscFunctionReturn(0); 6398b5c3584SJakub Kruzik } 6408b5c3584SJakub Kruzik 64104d534ceSJakub Kruzik static PetscErrorCode MatCompositeSetMergeFromRight_Composite(Mat mat,PetscBool flg) 64204d534ceSJakub Kruzik { 64304d534ceSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 64404d534ceSJakub Kruzik 64504d534ceSJakub Kruzik PetscFunctionBegin; 64604d534ceSJakub Kruzik shell->mergefromright = flg; 64704d534ceSJakub Kruzik PetscFunctionReturn(0); 64804d534ceSJakub Kruzik } 64904d534ceSJakub Kruzik 65004d534ceSJakub Kruzik /*@ 65104d534ceSJakub Kruzik MatCompositeSetMergeFromRight - Sets MatCompositeMerge() to start from right. 65204d534ceSJakub Kruzik 65304d534ceSJakub Kruzik Logically Collective on Mat 65404d534ceSJakub Kruzik 65504d534ceSJakub Kruzik Input Parameter: 65604d534ceSJakub Kruzik + mat - the composite matrix 65704d534ceSJakub Kruzik - flg - if true (default) the merge starts with the first added matrix (mat[0]) 65804d534ceSJakub Kruzik 65904d534ceSJakub Kruzik Level: advanced 66004d534ceSJakub Kruzik 6618bd739bdSJakub Kruzik Notes: 6628bd739bdSJakub Kruzik Has an effect only if the composite matrix is multiplicative. 6638bd739bdSJakub Kruzik 6648bd739bdSJakub Kruzik The resulting matrix is the same regardles of the flg. Only the order of operation is changed. 6658bd739bdSJakub Kruzik If flg is true the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0]))) 6668bd739bdSJakub Kruzik otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0]. 6678bd739bdSJakub Kruzik 6688bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE 66904d534ceSJakub Kruzik 67004d534ceSJakub Kruzik @*/ 67104d534ceSJakub Kruzik PetscErrorCode MatCompositeSetMergeFromRight(Mat mat,PetscBool flg) 67204d534ceSJakub Kruzik { 67304d534ceSJakub Kruzik PetscErrorCode ierr; 67404d534ceSJakub Kruzik 67504d534ceSJakub Kruzik PetscFunctionBegin; 67604d534ceSJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 67704d534ceSJakub Kruzik PetscValidLogicalCollectiveBool(mat,flg,2); 67804d534ceSJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeSetMergeFromRight_C",(Mat,PetscBool),(mat,flg));CHKERRQ(ierr); 67904d534ceSJakub Kruzik PetscFunctionReturn(0); 68004d534ceSJakub Kruzik } 68104d534ceSJakub Kruzik 68241cd0125SJakub Kruzik static struct _MatOps MatOps_Values = {0, 68341cd0125SJakub Kruzik 0, 68441cd0125SJakub Kruzik 0, 68541cd0125SJakub Kruzik MatMult_Composite, 6867bf3a71bSJakub Kruzik MatMultAdd_Composite, 68741cd0125SJakub Kruzik /* 5*/ MatMultTranspose_Composite, 6887bf3a71bSJakub Kruzik MatMultTransposeAdd_Composite, 68941cd0125SJakub Kruzik 0, 69041cd0125SJakub Kruzik 0, 69141cd0125SJakub Kruzik 0, 69241cd0125SJakub Kruzik /* 10*/ 0, 69341cd0125SJakub Kruzik 0, 69441cd0125SJakub Kruzik 0, 69541cd0125SJakub Kruzik 0, 69641cd0125SJakub Kruzik 0, 69741cd0125SJakub Kruzik /* 15*/ 0, 69841cd0125SJakub Kruzik 0, 69941cd0125SJakub Kruzik MatGetDiagonal_Composite, 70041cd0125SJakub Kruzik MatDiagonalScale_Composite, 70141cd0125SJakub Kruzik 0, 70241cd0125SJakub Kruzik /* 20*/ 0, 70341cd0125SJakub Kruzik MatAssemblyEnd_Composite, 70441cd0125SJakub Kruzik 0, 70541cd0125SJakub Kruzik 0, 70641cd0125SJakub Kruzik /* 24*/ 0, 70741cd0125SJakub Kruzik 0, 70841cd0125SJakub Kruzik 0, 70941cd0125SJakub Kruzik 0, 71041cd0125SJakub Kruzik 0, 71141cd0125SJakub Kruzik /* 29*/ 0, 71241cd0125SJakub Kruzik 0, 71341cd0125SJakub Kruzik 0, 71441cd0125SJakub Kruzik 0, 71541cd0125SJakub Kruzik 0, 71641cd0125SJakub Kruzik /* 34*/ 0, 71741cd0125SJakub Kruzik 0, 71841cd0125SJakub Kruzik 0, 71941cd0125SJakub Kruzik 0, 72041cd0125SJakub Kruzik 0, 72141cd0125SJakub Kruzik /* 39*/ 0, 72241cd0125SJakub Kruzik 0, 72341cd0125SJakub Kruzik 0, 72441cd0125SJakub Kruzik 0, 72541cd0125SJakub Kruzik 0, 72641cd0125SJakub Kruzik /* 44*/ 0, 72741cd0125SJakub Kruzik MatScale_Composite, 72841cd0125SJakub Kruzik MatShift_Basic, 72941cd0125SJakub Kruzik 0, 73041cd0125SJakub Kruzik 0, 73141cd0125SJakub Kruzik /* 49*/ 0, 73241cd0125SJakub Kruzik 0, 73341cd0125SJakub Kruzik 0, 73441cd0125SJakub Kruzik 0, 73541cd0125SJakub Kruzik 0, 73641cd0125SJakub Kruzik /* 54*/ 0, 73741cd0125SJakub Kruzik 0, 73841cd0125SJakub Kruzik 0, 73941cd0125SJakub Kruzik 0, 74041cd0125SJakub Kruzik 0, 74141cd0125SJakub Kruzik /* 59*/ 0, 74241cd0125SJakub Kruzik MatDestroy_Composite, 74341cd0125SJakub Kruzik 0, 74441cd0125SJakub Kruzik 0, 74541cd0125SJakub Kruzik 0, 74641cd0125SJakub Kruzik /* 64*/ 0, 74741cd0125SJakub Kruzik 0, 74841cd0125SJakub Kruzik 0, 74941cd0125SJakub Kruzik 0, 75041cd0125SJakub Kruzik 0, 75141cd0125SJakub Kruzik /* 69*/ 0, 75241cd0125SJakub Kruzik 0, 75341cd0125SJakub Kruzik 0, 75441cd0125SJakub Kruzik 0, 75541cd0125SJakub Kruzik 0, 75641cd0125SJakub Kruzik /* 74*/ 0, 75741cd0125SJakub Kruzik 0, 758*4b2558d6SJakub Kruzik MatSetFromOptions_Composite, 75941cd0125SJakub Kruzik 0, 76041cd0125SJakub Kruzik 0, 76141cd0125SJakub Kruzik /* 79*/ 0, 76241cd0125SJakub Kruzik 0, 76341cd0125SJakub Kruzik 0, 76441cd0125SJakub Kruzik 0, 76541cd0125SJakub Kruzik 0, 76641cd0125SJakub Kruzik /* 84*/ 0, 76741cd0125SJakub Kruzik 0, 76841cd0125SJakub Kruzik 0, 76941cd0125SJakub Kruzik 0, 77041cd0125SJakub Kruzik 0, 77141cd0125SJakub Kruzik /* 89*/ 0, 77241cd0125SJakub Kruzik 0, 77341cd0125SJakub Kruzik 0, 77441cd0125SJakub Kruzik 0, 77541cd0125SJakub Kruzik 0, 77641cd0125SJakub Kruzik /* 94*/ 0, 77741cd0125SJakub Kruzik 0, 77841cd0125SJakub Kruzik 0, 77941cd0125SJakub Kruzik 0, 78041cd0125SJakub Kruzik 0, 78141cd0125SJakub Kruzik /*99*/ 0, 78241cd0125SJakub Kruzik 0, 78341cd0125SJakub Kruzik 0, 78441cd0125SJakub Kruzik 0, 78541cd0125SJakub Kruzik 0, 78641cd0125SJakub Kruzik /*104*/ 0, 78741cd0125SJakub Kruzik 0, 78841cd0125SJakub Kruzik 0, 78941cd0125SJakub Kruzik 0, 79041cd0125SJakub Kruzik 0, 79141cd0125SJakub Kruzik /*109*/ 0, 79241cd0125SJakub Kruzik 0, 79341cd0125SJakub Kruzik 0, 79441cd0125SJakub Kruzik 0, 79541cd0125SJakub Kruzik 0, 79641cd0125SJakub Kruzik /*114*/ 0, 79741cd0125SJakub Kruzik 0, 79841cd0125SJakub Kruzik 0, 79941cd0125SJakub Kruzik 0, 80041cd0125SJakub Kruzik 0, 80141cd0125SJakub Kruzik /*119*/ 0, 80241cd0125SJakub Kruzik 0, 80341cd0125SJakub Kruzik 0, 80441cd0125SJakub Kruzik 0, 80541cd0125SJakub Kruzik 0, 80641cd0125SJakub Kruzik /*124*/ 0, 80741cd0125SJakub Kruzik 0, 80841cd0125SJakub Kruzik 0, 80941cd0125SJakub Kruzik 0, 81041cd0125SJakub Kruzik 0, 81141cd0125SJakub Kruzik /*129*/ 0, 81241cd0125SJakub Kruzik 0, 81341cd0125SJakub Kruzik 0, 81441cd0125SJakub Kruzik 0, 81541cd0125SJakub Kruzik 0, 81641cd0125SJakub Kruzik /*134*/ 0, 81741cd0125SJakub Kruzik 0, 81841cd0125SJakub Kruzik 0, 81941cd0125SJakub Kruzik 0, 82041cd0125SJakub Kruzik 0, 82141cd0125SJakub Kruzik /*139*/ 0, 82241cd0125SJakub Kruzik 0, 82341cd0125SJakub Kruzik 0 82441cd0125SJakub Kruzik }; 82541cd0125SJakub Kruzik 82641cd0125SJakub Kruzik /*MC 82741cd0125SJakub Kruzik MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices. 82841cd0125SJakub Kruzik The matrices need to have a correct size and parallel layout for the sum or product to be valid. 82941cd0125SJakub Kruzik 83041cd0125SJakub Kruzik Notes: 83141cd0125SJakub Kruzik to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE); 83241cd0125SJakub Kruzik 83341cd0125SJakub Kruzik Level: advanced 83441cd0125SJakub Kruzik 8356d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeMerge(), MatCompositeSetMergeFromRight(), MatCompositeGetNumberMat(), MatCompositeGetMat() 83641cd0125SJakub Kruzik M*/ 83741cd0125SJakub Kruzik 83841cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) 83941cd0125SJakub Kruzik { 84041cd0125SJakub Kruzik Mat_Composite *b; 84141cd0125SJakub Kruzik PetscErrorCode ierr; 84241cd0125SJakub Kruzik 84341cd0125SJakub Kruzik PetscFunctionBegin; 84441cd0125SJakub Kruzik ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 84541cd0125SJakub Kruzik A->data = (void*)b; 84641cd0125SJakub Kruzik ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 84741cd0125SJakub Kruzik 84841cd0125SJakub Kruzik ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 84941cd0125SJakub Kruzik ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 85041cd0125SJakub Kruzik 85141cd0125SJakub Kruzik A->assembled = PETSC_TRUE; 85241cd0125SJakub Kruzik A->preallocated = PETSC_TRUE; 85341cd0125SJakub Kruzik b->type = MAT_COMPOSITE_ADDITIVE; 85441cd0125SJakub Kruzik b->scale = 1.0; 85541cd0125SJakub Kruzik b->nmat = 0; 856*4b2558d6SJakub Kruzik b->merge = PETSC_FALSE; 85704d534ceSJakub Kruzik b->mergefromright = PETSC_TRUE; 85841cd0125SJakub Kruzik 85941cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr); 86041cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr); 8616dbc55e5SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr); 86241cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr); 8636d0add67SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNumberMat_C",MatCompositeGetNumberMat_Composite);CHKERRQ(ierr); 86441cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr); 86504d534ceSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeFromRight_C",MatCompositeSetMergeFromRight_Composite);CHKERRQ(ierr); 86641cd0125SJakub Kruzik 86741cd0125SJakub Kruzik ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr); 86841cd0125SJakub Kruzik PetscFunctionReturn(0); 86941cd0125SJakub Kruzik } 87041cd0125SJakub Kruzik 871