1793850ffSBarry Smith 2b45d2f2cSJed Brown #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; 18793850ffSBarry Smith } Mat_Composite; 19793850ffSBarry Smith 20793850ffSBarry Smith #undef __FUNCT__ 21793850ffSBarry Smith #define __FUNCT__ "MatDestroy_Composite" 22793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat) 23793850ffSBarry Smith { 24793850ffSBarry Smith PetscErrorCode ierr; 252c33bbaeSSatish Balay Mat_Composite *shell = (Mat_Composite*)mat->data; 266d7c1e57SBarry Smith Mat_CompositeLink next = shell->head,oldnext; 27793850ffSBarry Smith 28793850ffSBarry Smith PetscFunctionBegin; 29793850ffSBarry Smith while (next) { 306bf464f9SBarry Smith ierr = MatDestroy(&next->mat);CHKERRQ(ierr); 316d7c1e57SBarry Smith if (next->work && (!next->next || next->work != next->next->work)) { 326bf464f9SBarry Smith ierr = VecDestroy(&next->work);CHKERRQ(ierr); 336d7c1e57SBarry Smith } 346d7c1e57SBarry Smith oldnext = next; 35793850ffSBarry Smith next = next->next; 366d7c1e57SBarry Smith ierr = PetscFree(oldnext);CHKERRQ(ierr); 37793850ffSBarry Smith } 386bf464f9SBarry Smith ierr = VecDestroy(&shell->work);CHKERRQ(ierr); 396bf464f9SBarry Smith ierr = VecDestroy(&shell->left);CHKERRQ(ierr); 406bf464f9SBarry Smith ierr = VecDestroy(&shell->right);CHKERRQ(ierr); 416bf464f9SBarry Smith ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr); 426bf464f9SBarry Smith ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr); 436bf464f9SBarry Smith ierr = PetscFree(mat->data);CHKERRQ(ierr); 44793850ffSBarry Smith PetscFunctionReturn(0); 45793850ffSBarry Smith } 46793850ffSBarry Smith 47793850ffSBarry Smith #undef __FUNCT__ 486d7c1e57SBarry Smith #define __FUNCT__ "MatMult_Composite_Multiplicative" 496d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y) 506d7c1e57SBarry Smith { 516d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 526d7c1e57SBarry Smith Mat_CompositeLink next = shell->head; 536d7c1e57SBarry Smith PetscErrorCode ierr; 546d7c1e57SBarry Smith Vec in,out; 556d7c1e57SBarry Smith 566d7c1e57SBarry Smith PetscFunctionBegin; 57e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 586d7c1e57SBarry Smith in = x; 59e4fc5df0SBarry Smith if (shell->right) { 60e4fc5df0SBarry Smith if (!shell->rightwork) { 61e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 62e4fc5df0SBarry Smith } 63e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 64e4fc5df0SBarry Smith in = shell->rightwork; 65e4fc5df0SBarry Smith } 666d7c1e57SBarry Smith while (next->next) { 676d7c1e57SBarry Smith if (!next->work) { /* should reuse previous work if the same size */ 680298fd71SBarry Smith ierr = MatGetVecs(next->mat,NULL,&next->work);CHKERRQ(ierr); 696d7c1e57SBarry Smith } 706d7c1e57SBarry Smith out = next->work; 716d7c1e57SBarry Smith ierr = MatMult(next->mat,in,out);CHKERRQ(ierr); 726d7c1e57SBarry Smith in = out; 736d7c1e57SBarry Smith next = next->next; 746d7c1e57SBarry Smith } 756d7c1e57SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 76e4fc5df0SBarry Smith if (shell->left) { 77e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 78e4fc5df0SBarry Smith } 79e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 806d7c1e57SBarry Smith PetscFunctionReturn(0); 816d7c1e57SBarry Smith } 826d7c1e57SBarry Smith 836d7c1e57SBarry Smith #undef __FUNCT__ 846d7c1e57SBarry Smith #define __FUNCT__ "MatMultTranspose_Composite_Multiplicative" 856d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y) 866d7c1e57SBarry Smith { 876d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 886d7c1e57SBarry Smith Mat_CompositeLink tail = shell->tail; 896d7c1e57SBarry Smith PetscErrorCode ierr; 906d7c1e57SBarry Smith Vec in,out; 916d7c1e57SBarry Smith 926d7c1e57SBarry Smith PetscFunctionBegin; 93e32f2f54SBarry Smith if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 946d7c1e57SBarry Smith in = x; 95e4fc5df0SBarry Smith if (shell->left) { 96e4fc5df0SBarry Smith if (!shell->leftwork) { 97e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 98e4fc5df0SBarry Smith } 99e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 100e4fc5df0SBarry Smith in = shell->leftwork; 101e4fc5df0SBarry Smith } 1026d7c1e57SBarry Smith while (tail->prev) { 1036d7c1e57SBarry Smith if (!tail->prev->work) { /* should reuse previous work if the same size */ 1040298fd71SBarry Smith ierr = MatGetVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr); 1056d7c1e57SBarry Smith } 1066d7c1e57SBarry Smith out = tail->prev->work; 1076d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr); 1086d7c1e57SBarry Smith in = out; 1096d7c1e57SBarry Smith tail = tail->prev; 1106d7c1e57SBarry Smith } 1116d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr); 112e4fc5df0SBarry Smith if (shell->right) { 113e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 114e4fc5df0SBarry Smith } 115e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 1166d7c1e57SBarry Smith PetscFunctionReturn(0); 1176d7c1e57SBarry Smith } 1186d7c1e57SBarry Smith 1196d7c1e57SBarry Smith #undef __FUNCT__ 120793850ffSBarry Smith #define __FUNCT__ "MatMult_Composite" 121793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y) 122793850ffSBarry Smith { 123793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 124793850ffSBarry Smith Mat_CompositeLink next = shell->head; 125793850ffSBarry Smith PetscErrorCode ierr; 126e4fc5df0SBarry Smith Vec in; 127793850ffSBarry Smith 128793850ffSBarry Smith PetscFunctionBegin; 129e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 130e4fc5df0SBarry Smith in = x; 131e4fc5df0SBarry Smith if (shell->right) { 132e4fc5df0SBarry Smith if (!shell->rightwork) { 133e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 134793850ffSBarry Smith } 135e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 136e4fc5df0SBarry Smith in = shell->rightwork; 137e4fc5df0SBarry Smith } 138e4fc5df0SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 139e4fc5df0SBarry Smith while ((next = next->next)) { 140e4fc5df0SBarry Smith ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr); 141e4fc5df0SBarry Smith } 142e4fc5df0SBarry Smith if (shell->left) { 143e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 144e4fc5df0SBarry Smith } 145e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 146793850ffSBarry Smith PetscFunctionReturn(0); 147793850ffSBarry Smith } 148793850ffSBarry Smith 149793850ffSBarry Smith #undef __FUNCT__ 150793850ffSBarry Smith #define __FUNCT__ "MatMultTranspose_Composite" 151793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y) 152793850ffSBarry Smith { 153793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 154793850ffSBarry Smith Mat_CompositeLink next = shell->head; 155793850ffSBarry Smith PetscErrorCode ierr; 156e4fc5df0SBarry Smith Vec in; 157793850ffSBarry Smith 158793850ffSBarry Smith PetscFunctionBegin; 159e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 160e4fc5df0SBarry Smith in = x; 161e4fc5df0SBarry Smith if (shell->left) { 162e4fc5df0SBarry Smith if (!shell->leftwork) { 163e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 164793850ffSBarry Smith } 165e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 166e4fc5df0SBarry Smith in = shell->leftwork; 167e4fc5df0SBarry Smith } 168e4fc5df0SBarry Smith ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr); 169e4fc5df0SBarry Smith while ((next = next->next)) { 170e4fc5df0SBarry Smith ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr); 171e4fc5df0SBarry Smith } 172e4fc5df0SBarry Smith if (shell->right) { 173e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 174e4fc5df0SBarry Smith } 175e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 176793850ffSBarry Smith PetscFunctionReturn(0); 177793850ffSBarry Smith } 178793850ffSBarry Smith 179793850ffSBarry Smith #undef __FUNCT__ 180793850ffSBarry Smith #define __FUNCT__ "MatGetDiagonal_Composite" 181793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v) 182793850ffSBarry Smith { 183793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 184793850ffSBarry Smith Mat_CompositeLink next = shell->head; 185793850ffSBarry Smith PetscErrorCode ierr; 186793850ffSBarry Smith 187793850ffSBarry Smith PetscFunctionBegin; 188e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 189e32f2f54SBarry Smith if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling"); 190e4fc5df0SBarry Smith 191793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr); 192793850ffSBarry Smith if (next->next && !shell->work) { 193793850ffSBarry Smith ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr); 194793850ffSBarry Smith } 195793850ffSBarry Smith while ((next = next->next)) { 196793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr); 197793850ffSBarry Smith ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr); 198793850ffSBarry Smith } 199e4fc5df0SBarry Smith ierr = VecScale(v,shell->scale);CHKERRQ(ierr); 200793850ffSBarry Smith PetscFunctionReturn(0); 201793850ffSBarry Smith } 202793850ffSBarry Smith 203793850ffSBarry Smith #undef __FUNCT__ 204793850ffSBarry Smith #define __FUNCT__ "MatAssemblyEnd_Composite" 205793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t) 206793850ffSBarry Smith { 207b52f573bSBarry Smith PetscErrorCode ierr; 208ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 209b52f573bSBarry Smith 210793850ffSBarry Smith PetscFunctionBegin; 2110298fd71SBarry Smith ierr = PetscOptionsGetBool(((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr); 212b52f573bSBarry Smith if (flg) { 213b52f573bSBarry Smith ierr = MatCompositeMerge(Y);CHKERRQ(ierr); 214b52f573bSBarry Smith } 215793850ffSBarry Smith PetscFunctionReturn(0); 216793850ffSBarry Smith } 217793850ffSBarry Smith 218e4fc5df0SBarry Smith #undef __FUNCT__ 219e4fc5df0SBarry Smith #define __FUNCT__ "MatScale_Composite" 220e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha) 221e4fc5df0SBarry Smith { 222e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 223e4fc5df0SBarry Smith 224e4fc5df0SBarry Smith PetscFunctionBegin; 225321429dbSBarry Smith a->scale *= alpha; 226e4fc5df0SBarry Smith PetscFunctionReturn(0); 227e4fc5df0SBarry Smith } 228e4fc5df0SBarry Smith 229e4fc5df0SBarry Smith #undef __FUNCT__ 230e4fc5df0SBarry Smith #define __FUNCT__ "MatDiagonalScale_Composite" 231e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right) 232e4fc5df0SBarry Smith { 233e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 234e4fc5df0SBarry Smith PetscErrorCode ierr; 235e4fc5df0SBarry Smith 236e4fc5df0SBarry Smith PetscFunctionBegin; 237e4fc5df0SBarry Smith if (left) { 238321429dbSBarry Smith if (!a->left) { 239e4fc5df0SBarry Smith ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); 240e4fc5df0SBarry Smith ierr = VecCopy(left,a->left);CHKERRQ(ierr); 241321429dbSBarry Smith } else { 242321429dbSBarry Smith ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); 243321429dbSBarry Smith } 244e4fc5df0SBarry Smith } 245e4fc5df0SBarry Smith if (right) { 246321429dbSBarry Smith if (!a->right) { 247e4fc5df0SBarry Smith ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); 248e4fc5df0SBarry Smith ierr = VecCopy(right,a->right);CHKERRQ(ierr); 249321429dbSBarry Smith } else { 250321429dbSBarry Smith ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); 251321429dbSBarry Smith } 252e4fc5df0SBarry Smith } 253e4fc5df0SBarry Smith PetscFunctionReturn(0); 254e4fc5df0SBarry Smith } 255793850ffSBarry Smith 256793850ffSBarry Smith static struct _MatOps MatOps_Values = {0, 257793850ffSBarry Smith 0, 258793850ffSBarry Smith 0, 259793850ffSBarry Smith MatMult_Composite, 260793850ffSBarry Smith 0, 261793850ffSBarry Smith /* 5*/ MatMultTranspose_Composite, 262793850ffSBarry Smith 0, 263793850ffSBarry Smith 0, 264793850ffSBarry Smith 0, 265793850ffSBarry Smith 0, 266793850ffSBarry Smith /* 10*/ 0, 267793850ffSBarry Smith 0, 268793850ffSBarry Smith 0, 269793850ffSBarry Smith 0, 270793850ffSBarry Smith 0, 271793850ffSBarry Smith /* 15*/ 0, 272793850ffSBarry Smith 0, 273793850ffSBarry Smith MatGetDiagonal_Composite, 274e4fc5df0SBarry Smith MatDiagonalScale_Composite, 275793850ffSBarry Smith 0, 276793850ffSBarry Smith /* 20*/ 0, 277793850ffSBarry Smith MatAssemblyEnd_Composite, 278793850ffSBarry Smith 0, 279793850ffSBarry Smith 0, 280d519adbfSMatthew Knepley /* 24*/ 0, 281793850ffSBarry Smith 0, 282793850ffSBarry Smith 0, 283793850ffSBarry Smith 0, 284793850ffSBarry Smith 0, 285d519adbfSMatthew Knepley /* 29*/ 0, 286793850ffSBarry Smith 0, 287793850ffSBarry Smith 0, 288793850ffSBarry Smith 0, 289793850ffSBarry Smith 0, 290d519adbfSMatthew Knepley /* 34*/ 0, 291793850ffSBarry Smith 0, 292793850ffSBarry Smith 0, 293793850ffSBarry Smith 0, 294793850ffSBarry Smith 0, 295d519adbfSMatthew Knepley /* 39*/ 0, 296793850ffSBarry Smith 0, 297793850ffSBarry Smith 0, 298793850ffSBarry Smith 0, 299793850ffSBarry Smith 0, 300d519adbfSMatthew Knepley /* 44*/ 0, 301e4fc5df0SBarry Smith MatScale_Composite, 302793850ffSBarry Smith 0, 303793850ffSBarry Smith 0, 304793850ffSBarry Smith 0, 305d519adbfSMatthew Knepley /* 49*/ 0, 306793850ffSBarry Smith 0, 307793850ffSBarry Smith 0, 308793850ffSBarry Smith 0, 309793850ffSBarry Smith 0, 310d519adbfSMatthew Knepley /* 54*/ 0, 311793850ffSBarry Smith 0, 312793850ffSBarry Smith 0, 313793850ffSBarry Smith 0, 314793850ffSBarry Smith 0, 315d519adbfSMatthew Knepley /* 59*/ 0, 316793850ffSBarry Smith MatDestroy_Composite, 317793850ffSBarry Smith 0, 318793850ffSBarry Smith 0, 319793850ffSBarry Smith 0, 320d519adbfSMatthew Knepley /* 64*/ 0, 321793850ffSBarry Smith 0, 322793850ffSBarry Smith 0, 323793850ffSBarry Smith 0, 324793850ffSBarry Smith 0, 325d519adbfSMatthew Knepley /* 69*/ 0, 326793850ffSBarry Smith 0, 327793850ffSBarry Smith 0, 328793850ffSBarry Smith 0, 329793850ffSBarry Smith 0, 330d519adbfSMatthew Knepley /* 74*/ 0, 331793850ffSBarry Smith 0, 332793850ffSBarry Smith 0, 333793850ffSBarry Smith 0, 334793850ffSBarry Smith 0, 335d519adbfSMatthew Knepley /* 79*/ 0, 336793850ffSBarry Smith 0, 337793850ffSBarry Smith 0, 338793850ffSBarry Smith 0, 339793850ffSBarry Smith 0, 340d519adbfSMatthew Knepley /* 84*/ 0, 341793850ffSBarry Smith 0, 342793850ffSBarry Smith 0, 343793850ffSBarry Smith 0, 344793850ffSBarry Smith 0, 345d519adbfSMatthew Knepley /* 89*/ 0, 346793850ffSBarry Smith 0, 347793850ffSBarry Smith 0, 348793850ffSBarry Smith 0, 349793850ffSBarry Smith 0, 350d519adbfSMatthew Knepley /* 94*/ 0, 351793850ffSBarry Smith 0, 352793850ffSBarry Smith 0, 3533964eb88SJed Brown 0, 3543964eb88SJed Brown 0, 3553964eb88SJed Brown /*99*/ 0, 3563964eb88SJed Brown 0, 3573964eb88SJed Brown 0, 3583964eb88SJed Brown 0, 3593964eb88SJed Brown 0, 3603964eb88SJed Brown /*104*/ 0, 3613964eb88SJed Brown 0, 3623964eb88SJed Brown 0, 3633964eb88SJed Brown 0, 3643964eb88SJed Brown 0, 3653964eb88SJed Brown /*109*/ 0, 3663964eb88SJed Brown 0, 3673964eb88SJed Brown 0, 3683964eb88SJed Brown 0, 3693964eb88SJed Brown 0, 3703964eb88SJed Brown /*114*/ 0, 3713964eb88SJed Brown 0, 3723964eb88SJed Brown 0, 3733964eb88SJed Brown 0, 3743964eb88SJed Brown 0, 3753964eb88SJed Brown /*119*/ 0, 3763964eb88SJed Brown 0, 3773964eb88SJed Brown 0, 3783964eb88SJed Brown 0, 3793964eb88SJed Brown 0, 3803964eb88SJed Brown /*124*/ 0, 3813964eb88SJed Brown 0, 3823964eb88SJed Brown 0, 3833964eb88SJed Brown 0, 3843964eb88SJed Brown 0, 3853964eb88SJed Brown /*129*/ 0, 3863964eb88SJed Brown 0, 3873964eb88SJed Brown 0, 3883964eb88SJed Brown 0, 3893964eb88SJed Brown 0, 3903964eb88SJed Brown /*134*/ 0, 3913964eb88SJed Brown 0, 3923964eb88SJed Brown 0, 3933964eb88SJed Brown 0, 3943964eb88SJed Brown 0, 3953964eb88SJed Brown /*139*/ 0, 396*f9426fe0SMark Adams 0, 3973964eb88SJed Brown 0 3983964eb88SJed Brown }; 399793850ffSBarry Smith 400793850ffSBarry Smith /*MC 4016d7c1e57SBarry Smith MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices (all matrices are of same size and parallel layout). 4026d7c1e57SBarry Smith 4036d7c1e57SBarry Smith Notes: to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE); 404793850ffSBarry Smith 405793850ffSBarry Smith Level: advanced 406793850ffSBarry Smith 4076d7c1e57SBarry Smith .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType 408793850ffSBarry Smith M*/ 409793850ffSBarry Smith 410793850ffSBarry Smith #undef __FUNCT__ 411793850ffSBarry Smith #define __FUNCT__ "MatCreate_Composite" 4128cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) 413793850ffSBarry Smith { 414793850ffSBarry Smith Mat_Composite *b; 415793850ffSBarry Smith PetscErrorCode ierr; 416793850ffSBarry Smith 417793850ffSBarry Smith PetscFunctionBegin; 41838f2d2fdSLisandro Dalcin ierr = PetscNewLog(A,Mat_Composite,&b);CHKERRQ(ierr); 419793850ffSBarry Smith A->data = (void*)b; 42038f2d2fdSLisandro Dalcin ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 421793850ffSBarry Smith 42226283091SBarry Smith ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 42326283091SBarry Smith ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 424793850ffSBarry Smith 425793850ffSBarry Smith A->assembled = PETSC_TRUE; 4263db03f37SJed Brown A->preallocated = PETSC_TRUE; 4276d7c1e57SBarry Smith b->type = MAT_COMPOSITE_ADDITIVE; 428e4fc5df0SBarry Smith b->scale = 1.0; 429793850ffSBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr); 430793850ffSBarry Smith PetscFunctionReturn(0); 431793850ffSBarry Smith } 432793850ffSBarry Smith 433793850ffSBarry Smith #undef __FUNCT__ 434793850ffSBarry Smith #define __FUNCT__ "MatCreateComposite" 435793850ffSBarry Smith /*@C 436793850ffSBarry Smith MatCreateComposite - Creates a matrix as the sum of zero or more matrices 437793850ffSBarry Smith 438793850ffSBarry Smith Collective on MPI_Comm 439793850ffSBarry Smith 440793850ffSBarry Smith Input Parameters: 441793850ffSBarry Smith + comm - MPI communicator 442793850ffSBarry Smith . nmat - number of matrices to put in 443793850ffSBarry Smith - mats - the matrices 444793850ffSBarry Smith 445793850ffSBarry Smith Output Parameter: 446793850ffSBarry Smith . A - the matrix 447793850ffSBarry Smith 448793850ffSBarry Smith Level: advanced 449793850ffSBarry Smith 450793850ffSBarry Smith Notes: 451793850ffSBarry Smith Alternative construction 452793850ffSBarry Smith $ MatCreate(comm,&mat); 453793850ffSBarry Smith $ MatSetSizes(mat,m,n,M,N); 454793850ffSBarry Smith $ MatSetType(mat,MATCOMPOSITE); 455793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[0]); 456793850ffSBarry Smith $ .... 457793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[nmat-1]); 458b52f573bSBarry Smith $ MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); 459b52f573bSBarry Smith $ MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); 460793850ffSBarry Smith 4616d7c1e57SBarry Smith For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] 4626d7c1e57SBarry Smith 4636d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType 464793850ffSBarry Smith 465793850ffSBarry Smith @*/ 4667087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat) 467793850ffSBarry Smith { 468793850ffSBarry Smith PetscErrorCode ierr; 469793850ffSBarry Smith PetscInt m,n,M,N,i; 470793850ffSBarry Smith 471793850ffSBarry Smith PetscFunctionBegin; 472e32f2f54SBarry Smith if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix"); 473f3f84630SBarry Smith PetscValidPointer(mat,3); 474793850ffSBarry Smith 475793850ffSBarry Smith ierr = MatGetLocalSize(mats[0],&m,&n);CHKERRQ(ierr); 476793850ffSBarry Smith ierr = MatGetSize(mats[0],&M,&N);CHKERRQ(ierr); 477793850ffSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 478793850ffSBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 479793850ffSBarry Smith ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr); 480793850ffSBarry Smith for (i=0; i<nmat; i++) { 481793850ffSBarry Smith ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr); 482793850ffSBarry Smith } 483b52f573bSBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 484b52f573bSBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 485793850ffSBarry Smith PetscFunctionReturn(0); 486793850ffSBarry Smith } 487793850ffSBarry Smith 488793850ffSBarry Smith #undef __FUNCT__ 489793850ffSBarry Smith #define __FUNCT__ "MatCompositeAddMat" 490793850ffSBarry Smith /*@ 491793850ffSBarry Smith MatCompositeAddMat - add another matrix to a composite matrix 492793850ffSBarry Smith 493793850ffSBarry Smith Collective on Mat 494793850ffSBarry Smith 495793850ffSBarry Smith Input Parameters: 496793850ffSBarry Smith + mat - the composite matrix 497793850ffSBarry Smith - smat - the partial matrix 498793850ffSBarry Smith 499793850ffSBarry Smith Level: advanced 500793850ffSBarry Smith 501793850ffSBarry Smith .seealso: MatCreateComposite() 502793850ffSBarry Smith @*/ 5037087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat) 504793850ffSBarry Smith { 50538f2d2fdSLisandro Dalcin Mat_Composite *shell; 506793850ffSBarry Smith PetscErrorCode ierr; 507793850ffSBarry Smith Mat_CompositeLink ilink,next; 508793850ffSBarry Smith 509793850ffSBarry Smith PetscFunctionBegin; 5100700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 5110700a824SBarry Smith PetscValidHeaderSpecific(smat,MAT_CLASSID,2); 51238f2d2fdSLisandro Dalcin ierr = PetscNewLog(mat,struct _Mat_CompositeLink,&ilink);CHKERRQ(ierr); 513793850ffSBarry Smith ilink->next = 0; 514793850ffSBarry Smith ierr = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr); 515c3122656SLisandro Dalcin ilink->mat = smat; 516793850ffSBarry Smith 51738f2d2fdSLisandro Dalcin shell = (Mat_Composite*)mat->data; 518793850ffSBarry Smith next = shell->head; 5192205254eSKarl Rupp if (!next) shell->head = ilink; 5202205254eSKarl Rupp else { 521793850ffSBarry Smith while (next->next) { 522793850ffSBarry Smith next = next->next; 523793850ffSBarry Smith } 524793850ffSBarry Smith next->next = ilink; 5256d7c1e57SBarry Smith ilink->prev = next; 5266d7c1e57SBarry Smith } 5276d7c1e57SBarry Smith shell->tail = ilink; 5286d7c1e57SBarry Smith PetscFunctionReturn(0); 5296d7c1e57SBarry Smith } 5306d7c1e57SBarry Smith 5316d7c1e57SBarry Smith #undef __FUNCT__ 5326d7c1e57SBarry Smith #define __FUNCT__ "MatCompositeSetType" 5336d7c1e57SBarry Smith /*@C 5346d7c1e57SBarry Smith MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product 5356d7c1e57SBarry Smith 5366d7c1e57SBarry Smith Collective on MPI_Comm 5376d7c1e57SBarry Smith 5386d7c1e57SBarry Smith Input Parameters: 5396d7c1e57SBarry Smith . mat - the composite matrix 5406d7c1e57SBarry Smith 5416d7c1e57SBarry Smith 5426d7c1e57SBarry Smith Level: advanced 5436d7c1e57SBarry Smith 5446d7c1e57SBarry Smith Notes: 5456d7c1e57SBarry Smith The MatType of the resulting matrix will be the same as the MatType of the FIRST 5466d7c1e57SBarry Smith matrix in the composite matrix. 5476d7c1e57SBarry Smith 5486d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE 5496d7c1e57SBarry Smith 5506d7c1e57SBarry Smith @*/ 5517087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type) 5526d7c1e57SBarry Smith { 5536d7c1e57SBarry Smith Mat_Composite *b = (Mat_Composite*)mat->data; 554ace3abfcSBarry Smith PetscBool flg; 5556d7c1e57SBarry Smith PetscErrorCode ierr; 5566d7c1e57SBarry Smith 5576d7c1e57SBarry Smith PetscFunctionBegin; 558251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)mat,MATCOMPOSITE,&flg);CHKERRQ(ierr); 559e32f2f54SBarry Smith if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Can only use with composite matrix"); 5606d7c1e57SBarry Smith if (type == MAT_COMPOSITE_MULTIPLICATIVE) { 5616d7c1e57SBarry Smith mat->ops->getdiagonal = 0; 5626d7c1e57SBarry Smith mat->ops->mult = MatMult_Composite_Multiplicative; 5636d7c1e57SBarry Smith mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; 5646d7c1e57SBarry Smith b->type = MAT_COMPOSITE_MULTIPLICATIVE; 5656d7c1e57SBarry Smith } else { 5666d7c1e57SBarry Smith mat->ops->getdiagonal = MatGetDiagonal_Composite; 5676d7c1e57SBarry Smith mat->ops->mult = MatMult_Composite; 5686d7c1e57SBarry Smith mat->ops->multtranspose = MatMultTranspose_Composite; 5696d7c1e57SBarry Smith b->type = MAT_COMPOSITE_ADDITIVE; 570793850ffSBarry Smith } 571793850ffSBarry Smith PetscFunctionReturn(0); 572793850ffSBarry Smith } 573793850ffSBarry Smith 5746d7c1e57SBarry Smith 575b52f573bSBarry Smith #undef __FUNCT__ 576b52f573bSBarry Smith #define __FUNCT__ "MatCompositeMerge" 577b52f573bSBarry Smith /*@C 578b52f573bSBarry Smith MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix 579b52f573bSBarry Smith by summing all the matrices inside the composite matrix. 580b52f573bSBarry Smith 581b52f573bSBarry Smith Collective on MPI_Comm 582b52f573bSBarry Smith 583b52f573bSBarry Smith Input Parameters: 584b52f573bSBarry Smith . mat - the composite matrix 585b52f573bSBarry Smith 586b52f573bSBarry Smith 587b52f573bSBarry Smith Options Database: 588b52f573bSBarry Smith . -mat_composite_merge (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked) 589b52f573bSBarry Smith 590b52f573bSBarry Smith Level: advanced 591b52f573bSBarry Smith 592b52f573bSBarry Smith Notes: 593b52f573bSBarry Smith The MatType of the resulting matrix will be the same as the MatType of the FIRST 594b52f573bSBarry Smith matrix in the composite matrix. 595b52f573bSBarry Smith 596b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE 597b52f573bSBarry Smith 598b52f573bSBarry Smith @*/ 5997087cfbeSBarry Smith PetscErrorCode MatCompositeMerge(Mat mat) 600b52f573bSBarry Smith { 601b52f573bSBarry Smith Mat_Composite *shell = (Mat_Composite*)mat->data; 6026d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, prev = shell->tail; 603b52f573bSBarry Smith PetscErrorCode ierr; 6046d7c1e57SBarry Smith Mat tmat,newmat; 6051ba60692SJed Brown Vec left,right; 6061ba60692SJed Brown PetscScalar scale; 607b52f573bSBarry Smith 608b52f573bSBarry Smith PetscFunctionBegin; 609e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 610b52f573bSBarry Smith 611b52f573bSBarry Smith PetscFunctionBegin; 6126d7c1e57SBarry Smith if (shell->type == MAT_COMPOSITE_ADDITIVE) { 613b52f573bSBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 614b52f573bSBarry Smith while ((next = next->next)) { 615b52f573bSBarry Smith ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 616b52f573bSBarry Smith } 6176d7c1e57SBarry Smith } else { 6186d7c1e57SBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 6196d7c1e57SBarry Smith while ((prev = prev->prev)) { 6206d7c1e57SBarry Smith ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 6216bf464f9SBarry Smith ierr = MatDestroy(&tmat);CHKERRQ(ierr); 6226d7c1e57SBarry Smith tmat = newmat; 6236d7c1e57SBarry Smith } 6246d7c1e57SBarry Smith } 6251ba60692SJed Brown 6261ba60692SJed Brown scale = shell->scale; 6271ba60692SJed Brown if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);} 6281ba60692SJed Brown if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);} 6291ba60692SJed Brown 6306d7c1e57SBarry Smith ierr = MatHeaderReplace(mat,tmat);CHKERRQ(ierr); 6311ba60692SJed Brown 6321ba60692SJed Brown ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr); 6331ba60692SJed Brown ierr = MatScale(mat,scale);CHKERRQ(ierr); 6341ba60692SJed Brown ierr = VecDestroy(&left);CHKERRQ(ierr); 6351ba60692SJed Brown ierr = VecDestroy(&right);CHKERRQ(ierr); 636b52f573bSBarry Smith PetscFunctionReturn(0); 637b52f573bSBarry Smith } 638