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; 19793850ffSBarry Smith } Mat_Composite; 20793850ffSBarry Smith 21793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat) 22793850ffSBarry Smith { 23793850ffSBarry Smith PetscErrorCode ierr; 242c33bbaeSSatish Balay Mat_Composite *shell = (Mat_Composite*)mat->data; 256d7c1e57SBarry Smith Mat_CompositeLink next = shell->head,oldnext; 26793850ffSBarry Smith 27793850ffSBarry Smith PetscFunctionBegin; 28793850ffSBarry Smith while (next) { 296bf464f9SBarry Smith ierr = MatDestroy(&next->mat);CHKERRQ(ierr); 306d7c1e57SBarry Smith if (next->work && (!next->next || next->work != next->next->work)) { 316bf464f9SBarry Smith ierr = VecDestroy(&next->work);CHKERRQ(ierr); 326d7c1e57SBarry Smith } 336d7c1e57SBarry Smith oldnext = next; 34793850ffSBarry Smith next = next->next; 356d7c1e57SBarry Smith ierr = PetscFree(oldnext);CHKERRQ(ierr); 36793850ffSBarry Smith } 376bf464f9SBarry Smith ierr = VecDestroy(&shell->work);CHKERRQ(ierr); 386bf464f9SBarry Smith ierr = VecDestroy(&shell->left);CHKERRQ(ierr); 396bf464f9SBarry Smith ierr = VecDestroy(&shell->right);CHKERRQ(ierr); 406bf464f9SBarry Smith ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr); 416bf464f9SBarry Smith ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr); 426bf464f9SBarry Smith ierr = PetscFree(mat->data);CHKERRQ(ierr); 43793850ffSBarry Smith PetscFunctionReturn(0); 44793850ffSBarry Smith } 45793850ffSBarry Smith 466d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y) 476d7c1e57SBarry Smith { 486d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 496d7c1e57SBarry Smith Mat_CompositeLink next = shell->head; 506d7c1e57SBarry Smith PetscErrorCode ierr; 516d7c1e57SBarry Smith Vec in,out; 526d7c1e57SBarry Smith 536d7c1e57SBarry Smith PetscFunctionBegin; 54e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 556d7c1e57SBarry Smith in = x; 56e4fc5df0SBarry Smith if (shell->right) { 57e4fc5df0SBarry Smith if (!shell->rightwork) { 58e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 59e4fc5df0SBarry Smith } 60e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 61e4fc5df0SBarry Smith in = shell->rightwork; 62e4fc5df0SBarry Smith } 636d7c1e57SBarry Smith while (next->next) { 646d7c1e57SBarry Smith if (!next->work) { /* should reuse previous work if the same size */ 652a7a6963SBarry Smith ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr); 666d7c1e57SBarry Smith } 676d7c1e57SBarry Smith out = next->work; 686d7c1e57SBarry Smith ierr = MatMult(next->mat,in,out);CHKERRQ(ierr); 696d7c1e57SBarry Smith in = out; 706d7c1e57SBarry Smith next = next->next; 716d7c1e57SBarry Smith } 726d7c1e57SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 73e4fc5df0SBarry Smith if (shell->left) { 74e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 75e4fc5df0SBarry Smith } 76e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 776d7c1e57SBarry Smith PetscFunctionReturn(0); 786d7c1e57SBarry Smith } 796d7c1e57SBarry Smith 806d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y) 816d7c1e57SBarry Smith { 826d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 836d7c1e57SBarry Smith Mat_CompositeLink tail = shell->tail; 846d7c1e57SBarry Smith PetscErrorCode ierr; 856d7c1e57SBarry Smith Vec in,out; 866d7c1e57SBarry Smith 876d7c1e57SBarry Smith PetscFunctionBegin; 88e32f2f54SBarry Smith if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 896d7c1e57SBarry Smith in = x; 90e4fc5df0SBarry Smith if (shell->left) { 91e4fc5df0SBarry Smith if (!shell->leftwork) { 92e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 93e4fc5df0SBarry Smith } 94e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 95e4fc5df0SBarry Smith in = shell->leftwork; 96e4fc5df0SBarry Smith } 976d7c1e57SBarry Smith while (tail->prev) { 986d7c1e57SBarry Smith if (!tail->prev->work) { /* should reuse previous work if the same size */ 992a7a6963SBarry Smith ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr); 1006d7c1e57SBarry Smith } 1016d7c1e57SBarry Smith out = tail->prev->work; 1026d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr); 1036d7c1e57SBarry Smith in = out; 1046d7c1e57SBarry Smith tail = tail->prev; 1056d7c1e57SBarry Smith } 1066d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr); 107e4fc5df0SBarry Smith if (shell->right) { 108e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 109e4fc5df0SBarry Smith } 110e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 1116d7c1e57SBarry Smith PetscFunctionReturn(0); 1126d7c1e57SBarry Smith } 1136d7c1e57SBarry Smith 114793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y) 115793850ffSBarry Smith { 116793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 117793850ffSBarry Smith Mat_CompositeLink next = shell->head; 118793850ffSBarry Smith PetscErrorCode ierr; 119e4fc5df0SBarry Smith Vec in; 120793850ffSBarry Smith 121793850ffSBarry Smith PetscFunctionBegin; 122e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 123e4fc5df0SBarry Smith in = x; 124e4fc5df0SBarry Smith if (shell->right) { 125e4fc5df0SBarry Smith if (!shell->rightwork) { 126e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 127793850ffSBarry Smith } 128e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 129e4fc5df0SBarry Smith in = shell->rightwork; 130e4fc5df0SBarry Smith } 131e4fc5df0SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 132e4fc5df0SBarry Smith while ((next = next->next)) { 133e4fc5df0SBarry Smith ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr); 134e4fc5df0SBarry Smith } 135e4fc5df0SBarry Smith if (shell->left) { 136e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 137e4fc5df0SBarry Smith } 138e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 139793850ffSBarry Smith PetscFunctionReturn(0); 140793850ffSBarry Smith } 141793850ffSBarry Smith 142793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y) 143793850ffSBarry Smith { 144793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 145793850ffSBarry Smith Mat_CompositeLink next = shell->head; 146793850ffSBarry Smith PetscErrorCode ierr; 147e4fc5df0SBarry Smith Vec in; 148793850ffSBarry Smith 149793850ffSBarry Smith PetscFunctionBegin; 150e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 151e4fc5df0SBarry Smith in = x; 152e4fc5df0SBarry Smith if (shell->left) { 153e4fc5df0SBarry Smith if (!shell->leftwork) { 154e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 155793850ffSBarry Smith } 156e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 157e4fc5df0SBarry Smith in = shell->leftwork; 158e4fc5df0SBarry Smith } 159e4fc5df0SBarry Smith ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr); 160e4fc5df0SBarry Smith while ((next = next->next)) { 161e4fc5df0SBarry Smith ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr); 162e4fc5df0SBarry Smith } 163e4fc5df0SBarry Smith if (shell->right) { 164e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 165e4fc5df0SBarry Smith } 166e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 167793850ffSBarry Smith PetscFunctionReturn(0); 168793850ffSBarry Smith } 169793850ffSBarry Smith 170793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v) 171793850ffSBarry Smith { 172793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 173793850ffSBarry Smith Mat_CompositeLink next = shell->head; 174793850ffSBarry Smith PetscErrorCode ierr; 175793850ffSBarry Smith 176793850ffSBarry Smith PetscFunctionBegin; 177e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 178e32f2f54SBarry Smith if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling"); 179e4fc5df0SBarry Smith 180793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr); 181793850ffSBarry Smith if (next->next && !shell->work) { 182793850ffSBarry Smith ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr); 183793850ffSBarry Smith } 184793850ffSBarry Smith while ((next = next->next)) { 185793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr); 186793850ffSBarry Smith ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr); 187793850ffSBarry Smith } 188e4fc5df0SBarry Smith ierr = VecScale(v,shell->scale);CHKERRQ(ierr); 189793850ffSBarry Smith PetscFunctionReturn(0); 190793850ffSBarry Smith } 191793850ffSBarry Smith 192793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t) 193793850ffSBarry Smith { 194b52f573bSBarry Smith PetscErrorCode ierr; 195ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 196b52f573bSBarry Smith 197793850ffSBarry Smith PetscFunctionBegin; 198c5929fdfSBarry Smith ierr = PetscOptionsGetBool(((PetscObject)Y)->options,((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr); 199b52f573bSBarry Smith if (flg) { 200b52f573bSBarry Smith ierr = MatCompositeMerge(Y);CHKERRQ(ierr); 201b52f573bSBarry Smith } 202793850ffSBarry Smith PetscFunctionReturn(0); 203793850ffSBarry Smith } 204793850ffSBarry Smith 205e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha) 206e4fc5df0SBarry Smith { 207e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 208e4fc5df0SBarry Smith 209e4fc5df0SBarry Smith PetscFunctionBegin; 210321429dbSBarry Smith a->scale *= alpha; 211e4fc5df0SBarry Smith PetscFunctionReturn(0); 212e4fc5df0SBarry Smith } 213e4fc5df0SBarry Smith 214e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right) 215e4fc5df0SBarry Smith { 216e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 217e4fc5df0SBarry Smith PetscErrorCode ierr; 218e4fc5df0SBarry Smith 219e4fc5df0SBarry Smith PetscFunctionBegin; 220e4fc5df0SBarry Smith if (left) { 221321429dbSBarry Smith if (!a->left) { 222e4fc5df0SBarry Smith ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); 223e4fc5df0SBarry Smith ierr = VecCopy(left,a->left);CHKERRQ(ierr); 224321429dbSBarry Smith } else { 225321429dbSBarry Smith ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); 226321429dbSBarry Smith } 227e4fc5df0SBarry Smith } 228e4fc5df0SBarry Smith if (right) { 229321429dbSBarry Smith if (!a->right) { 230e4fc5df0SBarry Smith ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); 231e4fc5df0SBarry Smith ierr = VecCopy(right,a->right);CHKERRQ(ierr); 232321429dbSBarry Smith } else { 233321429dbSBarry Smith ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); 234321429dbSBarry Smith } 235e4fc5df0SBarry Smith } 236e4fc5df0SBarry Smith PetscFunctionReturn(0); 237e4fc5df0SBarry Smith } 238793850ffSBarry Smith 239793850ffSBarry Smith static struct _MatOps MatOps_Values = {0, 240793850ffSBarry Smith 0, 241793850ffSBarry Smith 0, 242793850ffSBarry Smith MatMult_Composite, 243793850ffSBarry Smith 0, 244793850ffSBarry Smith /* 5*/ MatMultTranspose_Composite, 245793850ffSBarry Smith 0, 246793850ffSBarry Smith 0, 247793850ffSBarry Smith 0, 248793850ffSBarry Smith 0, 249793850ffSBarry Smith /* 10*/ 0, 250793850ffSBarry Smith 0, 251793850ffSBarry Smith 0, 252793850ffSBarry Smith 0, 253793850ffSBarry Smith 0, 254793850ffSBarry Smith /* 15*/ 0, 255793850ffSBarry Smith 0, 256793850ffSBarry Smith MatGetDiagonal_Composite, 257e4fc5df0SBarry Smith MatDiagonalScale_Composite, 258793850ffSBarry Smith 0, 259793850ffSBarry Smith /* 20*/ 0, 260793850ffSBarry Smith MatAssemblyEnd_Composite, 261793850ffSBarry Smith 0, 262793850ffSBarry Smith 0, 263d519adbfSMatthew Knepley /* 24*/ 0, 264793850ffSBarry Smith 0, 265793850ffSBarry Smith 0, 266793850ffSBarry Smith 0, 267793850ffSBarry Smith 0, 268d519adbfSMatthew Knepley /* 29*/ 0, 269793850ffSBarry Smith 0, 270793850ffSBarry Smith 0, 271793850ffSBarry Smith 0, 272793850ffSBarry Smith 0, 273d519adbfSMatthew Knepley /* 34*/ 0, 274793850ffSBarry Smith 0, 275793850ffSBarry Smith 0, 276793850ffSBarry Smith 0, 277793850ffSBarry Smith 0, 278d519adbfSMatthew Knepley /* 39*/ 0, 279793850ffSBarry Smith 0, 280793850ffSBarry Smith 0, 281793850ffSBarry Smith 0, 282793850ffSBarry Smith 0, 283d519adbfSMatthew Knepley /* 44*/ 0, 284e4fc5df0SBarry Smith MatScale_Composite, 2857d68702bSBarry Smith MatShift_Basic, 286793850ffSBarry Smith 0, 287793850ffSBarry Smith 0, 288d519adbfSMatthew Knepley /* 49*/ 0, 289793850ffSBarry Smith 0, 290793850ffSBarry Smith 0, 291793850ffSBarry Smith 0, 292793850ffSBarry Smith 0, 293d519adbfSMatthew Knepley /* 54*/ 0, 294793850ffSBarry Smith 0, 295793850ffSBarry Smith 0, 296793850ffSBarry Smith 0, 297793850ffSBarry Smith 0, 298d519adbfSMatthew Knepley /* 59*/ 0, 299793850ffSBarry Smith MatDestroy_Composite, 300793850ffSBarry Smith 0, 301793850ffSBarry Smith 0, 302793850ffSBarry Smith 0, 303d519adbfSMatthew Knepley /* 64*/ 0, 304793850ffSBarry Smith 0, 305793850ffSBarry Smith 0, 306793850ffSBarry Smith 0, 307793850ffSBarry Smith 0, 308d519adbfSMatthew Knepley /* 69*/ 0, 309793850ffSBarry Smith 0, 310793850ffSBarry Smith 0, 311793850ffSBarry Smith 0, 312793850ffSBarry Smith 0, 313d519adbfSMatthew Knepley /* 74*/ 0, 314793850ffSBarry Smith 0, 315793850ffSBarry Smith 0, 316793850ffSBarry Smith 0, 317793850ffSBarry Smith 0, 318d519adbfSMatthew Knepley /* 79*/ 0, 319793850ffSBarry Smith 0, 320793850ffSBarry Smith 0, 321793850ffSBarry Smith 0, 322793850ffSBarry Smith 0, 323d519adbfSMatthew Knepley /* 84*/ 0, 324793850ffSBarry Smith 0, 325793850ffSBarry Smith 0, 326793850ffSBarry Smith 0, 327793850ffSBarry Smith 0, 328d519adbfSMatthew Knepley /* 89*/ 0, 329793850ffSBarry Smith 0, 330793850ffSBarry Smith 0, 331793850ffSBarry Smith 0, 332793850ffSBarry Smith 0, 333d519adbfSMatthew Knepley /* 94*/ 0, 334793850ffSBarry Smith 0, 335793850ffSBarry Smith 0, 3363964eb88SJed Brown 0, 3373964eb88SJed Brown 0, 3383964eb88SJed Brown /*99*/ 0, 3393964eb88SJed Brown 0, 3403964eb88SJed Brown 0, 3413964eb88SJed Brown 0, 3423964eb88SJed Brown 0, 3433964eb88SJed Brown /*104*/ 0, 3443964eb88SJed Brown 0, 3453964eb88SJed Brown 0, 3463964eb88SJed Brown 0, 3473964eb88SJed Brown 0, 3483964eb88SJed Brown /*109*/ 0, 3493964eb88SJed Brown 0, 3503964eb88SJed Brown 0, 3513964eb88SJed Brown 0, 3523964eb88SJed Brown 0, 3533964eb88SJed Brown /*114*/ 0, 3543964eb88SJed Brown 0, 3553964eb88SJed Brown 0, 3563964eb88SJed Brown 0, 3573964eb88SJed Brown 0, 3583964eb88SJed Brown /*119*/ 0, 3593964eb88SJed Brown 0, 3603964eb88SJed Brown 0, 3613964eb88SJed Brown 0, 3623964eb88SJed Brown 0, 3633964eb88SJed Brown /*124*/ 0, 3643964eb88SJed Brown 0, 3653964eb88SJed Brown 0, 3663964eb88SJed Brown 0, 3673964eb88SJed Brown 0, 3683964eb88SJed Brown /*129*/ 0, 3693964eb88SJed Brown 0, 3703964eb88SJed Brown 0, 3713964eb88SJed Brown 0, 3723964eb88SJed Brown 0, 3733964eb88SJed Brown /*134*/ 0, 3743964eb88SJed Brown 0, 3753964eb88SJed Brown 0, 3763964eb88SJed Brown 0, 3773964eb88SJed Brown 0, 3783964eb88SJed Brown /*139*/ 0, 379f9426fe0SMark Adams 0, 3803964eb88SJed Brown 0 3813964eb88SJed Brown }; 382793850ffSBarry Smith 383793850ffSBarry Smith /*MC 384*c4f13f43SJakub Kruzik MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices. 385*c4f13f43SJakub Kruzik The matrices need to have a correct size and parallel layout for the sum or product to be valid. 3866d7c1e57SBarry Smith 38795452b02SPatrick Sanan Notes: 38895452b02SPatrick Sanan to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE); 389793850ffSBarry Smith 390793850ffSBarry Smith Level: advanced 391793850ffSBarry Smith 3926d7c1e57SBarry Smith .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType 393793850ffSBarry Smith M*/ 394793850ffSBarry Smith 3958cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) 396793850ffSBarry Smith { 397793850ffSBarry Smith Mat_Composite *b; 398793850ffSBarry Smith PetscErrorCode ierr; 399793850ffSBarry Smith 400793850ffSBarry Smith PetscFunctionBegin; 401b00a9115SJed Brown ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 402793850ffSBarry Smith A->data = (void*)b; 40338f2d2fdSLisandro Dalcin ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 404793850ffSBarry Smith 40526283091SBarry Smith ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 40626283091SBarry Smith ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 407793850ffSBarry Smith 408793850ffSBarry Smith A->assembled = PETSC_TRUE; 4093db03f37SJed Brown A->preallocated = PETSC_TRUE; 4106d7c1e57SBarry Smith b->type = MAT_COMPOSITE_ADDITIVE; 411e4fc5df0SBarry Smith b->scale = 1.0; 4126a7ede75SJakub Kruzik b->nmat = 0; 413793850ffSBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr); 414793850ffSBarry Smith PetscFunctionReturn(0); 415793850ffSBarry Smith } 416793850ffSBarry Smith 4172c0821f3SBarry Smith /*@ 418793850ffSBarry Smith MatCreateComposite - Creates a matrix as the sum of zero or more matrices 419793850ffSBarry Smith 420793850ffSBarry Smith Collective on MPI_Comm 421793850ffSBarry Smith 422793850ffSBarry Smith Input Parameters: 423793850ffSBarry Smith + comm - MPI communicator 424793850ffSBarry Smith . nmat - number of matrices to put in 425793850ffSBarry Smith - mats - the matrices 426793850ffSBarry Smith 427793850ffSBarry Smith Output Parameter: 428db36af27SMatthew G. Knepley . mat - the matrix 429793850ffSBarry Smith 430793850ffSBarry Smith Level: advanced 431793850ffSBarry Smith 432793850ffSBarry Smith Notes: 433793850ffSBarry Smith Alternative construction 434793850ffSBarry Smith $ MatCreate(comm,&mat); 435793850ffSBarry Smith $ MatSetSizes(mat,m,n,M,N); 436793850ffSBarry Smith $ MatSetType(mat,MATCOMPOSITE); 437793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[0]); 438793850ffSBarry Smith $ .... 439793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[nmat-1]); 440b52f573bSBarry Smith $ MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); 441b52f573bSBarry Smith $ MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); 442793850ffSBarry Smith 4436d7c1e57SBarry Smith For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] 4446d7c1e57SBarry Smith 4456d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType 446793850ffSBarry Smith 447793850ffSBarry Smith @*/ 4487087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat) 449793850ffSBarry Smith { 450793850ffSBarry Smith PetscErrorCode ierr; 451793850ffSBarry Smith PetscInt m,n,M,N,i; 452793850ffSBarry Smith 453793850ffSBarry Smith PetscFunctionBegin; 454e32f2f54SBarry Smith if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix"); 455f3f84630SBarry Smith PetscValidPointer(mat,3); 456793850ffSBarry Smith 457*c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr); 458*c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr); 459*c4f13f43SJakub Kruzik ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr); 460*c4f13f43SJakub Kruzik ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr); 461793850ffSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 462793850ffSBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 463793850ffSBarry Smith ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr); 464793850ffSBarry Smith for (i=0; i<nmat; i++) { 465793850ffSBarry Smith ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr); 466793850ffSBarry Smith } 467b52f573bSBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 468b52f573bSBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 469793850ffSBarry Smith PetscFunctionReturn(0); 470793850ffSBarry Smith } 471793850ffSBarry Smith 472793850ffSBarry Smith /*@ 473793850ffSBarry Smith MatCompositeAddMat - add another matrix to a composite matrix 474793850ffSBarry Smith 475793850ffSBarry Smith Collective on Mat 476793850ffSBarry Smith 477793850ffSBarry Smith Input Parameters: 478793850ffSBarry Smith + mat - the composite matrix 479793850ffSBarry Smith - smat - the partial matrix 480793850ffSBarry Smith 481793850ffSBarry Smith Level: advanced 482793850ffSBarry Smith 483793850ffSBarry Smith .seealso: MatCreateComposite() 484793850ffSBarry Smith @*/ 4857087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat) 486793850ffSBarry Smith { 48738f2d2fdSLisandro Dalcin Mat_Composite *shell; 488793850ffSBarry Smith PetscErrorCode ierr; 489793850ffSBarry Smith Mat_CompositeLink ilink,next; 490793850ffSBarry Smith 491793850ffSBarry Smith PetscFunctionBegin; 4920700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 4930700a824SBarry Smith PetscValidHeaderSpecific(smat,MAT_CLASSID,2); 494b00a9115SJed Brown ierr = PetscNewLog(mat,&ilink);CHKERRQ(ierr); 495793850ffSBarry Smith ilink->next = 0; 496793850ffSBarry Smith ierr = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr); 497c3122656SLisandro Dalcin ilink->mat = smat; 498793850ffSBarry Smith 49938f2d2fdSLisandro Dalcin shell = (Mat_Composite*)mat->data; 500793850ffSBarry Smith next = shell->head; 5012205254eSKarl Rupp if (!next) shell->head = ilink; 5022205254eSKarl Rupp else { 503793850ffSBarry Smith while (next->next) { 504793850ffSBarry Smith next = next->next; 505793850ffSBarry Smith } 506793850ffSBarry Smith next->next = ilink; 5076d7c1e57SBarry Smith ilink->prev = next; 5086d7c1e57SBarry Smith } 5096d7c1e57SBarry Smith shell->tail = ilink; 5106a7ede75SJakub Kruzik shell->nmat += 1; 5116d7c1e57SBarry Smith PetscFunctionReturn(0); 5126d7c1e57SBarry Smith } 5136d7c1e57SBarry Smith 5142c0821f3SBarry Smith /*@ 5156d7c1e57SBarry Smith MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product 5166d7c1e57SBarry Smith 5176d7c1e57SBarry Smith Collective on MPI_Comm 5186d7c1e57SBarry Smith 5196d7c1e57SBarry Smith Input Parameters: 5206d7c1e57SBarry Smith . mat - the composite matrix 5216d7c1e57SBarry Smith 5226d7c1e57SBarry Smith 5236d7c1e57SBarry Smith Level: advanced 5246d7c1e57SBarry Smith 5256d7c1e57SBarry Smith Notes: 5266d7c1e57SBarry Smith The MatType of the resulting matrix will be the same as the MatType of the FIRST 5276d7c1e57SBarry Smith matrix in the composite matrix. 5286d7c1e57SBarry Smith 5296d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE 5306d7c1e57SBarry Smith 5316d7c1e57SBarry Smith @*/ 5327087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type) 5336d7c1e57SBarry Smith { 5346d7c1e57SBarry Smith Mat_Composite *b = (Mat_Composite*)mat->data; 535ace3abfcSBarry Smith PetscBool flg; 5366d7c1e57SBarry Smith PetscErrorCode ierr; 5376d7c1e57SBarry Smith 5386d7c1e57SBarry Smith PetscFunctionBegin; 539251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)mat,MATCOMPOSITE,&flg);CHKERRQ(ierr); 540e32f2f54SBarry Smith if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Can only use with composite matrix"); 5416d7c1e57SBarry Smith if (type == MAT_COMPOSITE_MULTIPLICATIVE) { 5426d7c1e57SBarry Smith mat->ops->getdiagonal = 0; 5436d7c1e57SBarry Smith mat->ops->mult = MatMult_Composite_Multiplicative; 5446d7c1e57SBarry Smith mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; 5456d7c1e57SBarry Smith b->type = MAT_COMPOSITE_MULTIPLICATIVE; 5466d7c1e57SBarry Smith } else { 5476d7c1e57SBarry Smith mat->ops->getdiagonal = MatGetDiagonal_Composite; 5486d7c1e57SBarry Smith mat->ops->mult = MatMult_Composite; 5496d7c1e57SBarry Smith mat->ops->multtranspose = MatMultTranspose_Composite; 5506d7c1e57SBarry Smith b->type = MAT_COMPOSITE_ADDITIVE; 551793850ffSBarry Smith } 552793850ffSBarry Smith PetscFunctionReturn(0); 553793850ffSBarry Smith } 554793850ffSBarry Smith 5556d7c1e57SBarry Smith 5567e8dbf47SJed Brown /*@ 557b52f573bSBarry Smith MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix 558b52f573bSBarry Smith by summing all the matrices inside the composite matrix. 559b52f573bSBarry Smith 560b52f573bSBarry Smith Collective on MPI_Comm 561b52f573bSBarry Smith 562b52f573bSBarry Smith Input Parameters: 563b52f573bSBarry Smith . mat - the composite matrix 564b52f573bSBarry Smith 565b52f573bSBarry Smith 566b52f573bSBarry Smith Options Database: 567b52f573bSBarry Smith . -mat_composite_merge (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked) 568b52f573bSBarry Smith 569b52f573bSBarry Smith Level: advanced 570b52f573bSBarry Smith 571b52f573bSBarry Smith Notes: 572b52f573bSBarry Smith The MatType of the resulting matrix will be the same as the MatType of the FIRST 573b52f573bSBarry Smith matrix in the composite matrix. 574b52f573bSBarry Smith 575b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE 576b52f573bSBarry Smith 577b52f573bSBarry Smith @*/ 5787087cfbeSBarry Smith PetscErrorCode MatCompositeMerge(Mat mat) 579b52f573bSBarry Smith { 580b52f573bSBarry Smith Mat_Composite *shell = (Mat_Composite*)mat->data; 5816d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, prev = shell->tail; 582b52f573bSBarry Smith PetscErrorCode ierr; 5836d7c1e57SBarry Smith Mat tmat,newmat; 5841ba60692SJed Brown Vec left,right; 5851ba60692SJed Brown PetscScalar scale; 586b52f573bSBarry Smith 587b52f573bSBarry Smith PetscFunctionBegin; 588e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 589b52f573bSBarry Smith 590b52f573bSBarry Smith PetscFunctionBegin; 5916d7c1e57SBarry Smith if (shell->type == MAT_COMPOSITE_ADDITIVE) { 592b52f573bSBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 593b52f573bSBarry Smith while ((next = next->next)) { 594b52f573bSBarry Smith ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 595b52f573bSBarry Smith } 5966d7c1e57SBarry Smith } else { 5976d7c1e57SBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 5986d7c1e57SBarry Smith while ((prev = prev->prev)) { 5996d7c1e57SBarry Smith ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 6006bf464f9SBarry Smith ierr = MatDestroy(&tmat);CHKERRQ(ierr); 6016d7c1e57SBarry Smith tmat = newmat; 6026d7c1e57SBarry Smith } 6036d7c1e57SBarry Smith } 6041ba60692SJed Brown 6051ba60692SJed Brown scale = shell->scale; 6061ba60692SJed Brown if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);} 6071ba60692SJed Brown if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);} 6081ba60692SJed Brown 60928be2f97SBarry Smith ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr); 6101ba60692SJed Brown 6111ba60692SJed Brown ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr); 6121ba60692SJed Brown ierr = MatScale(mat,scale);CHKERRQ(ierr); 6131ba60692SJed Brown ierr = VecDestroy(&left);CHKERRQ(ierr); 6141ba60692SJed Brown ierr = VecDestroy(&right);CHKERRQ(ierr); 615b52f573bSBarry Smith PetscFunctionReturn(0); 616b52f573bSBarry Smith } 6176a7ede75SJakub Kruzik 6186a7ede75SJakub Kruzik /*@ 6196a7ede75SJakub Kruzik MatCompositeGetNMat - Returns the number of matrices in composite. 6206a7ede75SJakub Kruzik 6216a7ede75SJakub Kruzik Not Collective 6226a7ede75SJakub Kruzik 6236a7ede75SJakub Kruzik Input Parameter: 6246a7ede75SJakub Kruzik . A - the composite matrix 6256a7ede75SJakub Kruzik 6266a7ede75SJakub Kruzik Output Parameter: 6276a7ede75SJakub Kruzik . size - the local size 6286a7ede75SJakub Kruzik . nmat - number of matrices in composite 6296a7ede75SJakub Kruzik 6308b5c3584SJakub Kruzik Level: advanced 6316a7ede75SJakub Kruzik 6328b5c3584SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat() 6336a7ede75SJakub Kruzik 6346a7ede75SJakub Kruzik @*/ 6356a7ede75SJakub Kruzik PetscErrorCode MatCompositeGetNMat(Mat A,PetscInt *nmat) 6366a7ede75SJakub Kruzik { 6376a7ede75SJakub Kruzik Mat_Composite *shell; 6386a7ede75SJakub Kruzik 6396a7ede75SJakub Kruzik PetscFunctionBegin; 6406a7ede75SJakub Kruzik PetscValidHeaderSpecific(A,MAT_CLASSID,1); 6416a7ede75SJakub Kruzik PetscValidPointer(nmat,2); 6426a7ede75SJakub Kruzik shell = (Mat_Composite*)A->data; 6436a7ede75SJakub Kruzik *nmat = shell->nmat; 6446a7ede75SJakub Kruzik PetscFunctionReturn(0); 6456a7ede75SJakub Kruzik } 6466a7ede75SJakub Kruzik 6478b5c3584SJakub Kruzik /*@ 6488b5c3584SJakub Kruzik MatCompositeGetMat - Returns the ith matrix from composite. 6498b5c3584SJakub Kruzik 6508b5c3584SJakub Kruzik Logically Collective on Mat 6518b5c3584SJakub Kruzik 6528b5c3584SJakub Kruzik Input Parameter: 6538b5c3584SJakub Kruzik + A - the composite matrix 6548b5c3584SJakub Kruzik - i - the number of requested matrix 6558b5c3584SJakub Kruzik 6568b5c3584SJakub Kruzik Output Parameter: 6578b5c3584SJakub Kruzik . Ai - ith matrix in composite 6588b5c3584SJakub Kruzik 6598b5c3584SJakub Kruzik Level: advanced 6608b5c3584SJakub Kruzik 6618b5c3584SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNMat() 6628b5c3584SJakub Kruzik 6638b5c3584SJakub Kruzik @*/ 6648b5c3584SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat A,PetscInt i,Mat *Ai) 6658b5c3584SJakub Kruzik { 6668b5c3584SJakub Kruzik Mat_Composite *shell; 6678b5c3584SJakub Kruzik Mat_CompositeLink ilink; 6688b5c3584SJakub Kruzik PetscInt k; 6698b5c3584SJakub Kruzik 6708b5c3584SJakub Kruzik PetscFunctionBegin; 6718b5c3584SJakub Kruzik PetscValidHeaderSpecific(A,MAT_CLASSID,1); 6728b5c3584SJakub Kruzik PetscValidLogicalCollectiveInt(A,i,2); 6738b5c3584SJakub Kruzik PetscValidPointer(Ai,3); 6748b5c3584SJakub Kruzik shell = (Mat_Composite*)A->data; 6758b5c3584SJakub Kruzik if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat); 6768b5c3584SJakub Kruzik ilink = shell->head; 6778b5c3584SJakub Kruzik for (k=0; k<i; k++) { 6788b5c3584SJakub Kruzik if (ilink) { 6798b5c3584SJakub Kruzik ilink = ilink->next; 6808b5c3584SJakub Kruzik } else { 6818b5c3584SJakub Kruzik break; 6828b5c3584SJakub Kruzik } 6838b5c3584SJakub Kruzik } 6848b5c3584SJakub Kruzik *Ai = ilink->mat; 6858b5c3584SJakub Kruzik PetscFunctionReturn(0); 6868b5c3584SJakub Kruzik } 6878b5c3584SJakub Kruzik 688