1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 2793850ffSBarry Smith 3f4259b30SLisandro Dalcin const char *const MatCompositeMergeTypes[] = {"left", "right", "MatCompositeMergeType", "MAT_COMPOSITE_", NULL}; 48c8613bfSJakub Kruzik 5793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink; 6793850ffSBarry Smith struct _Mat_CompositeLink { 7793850ffSBarry Smith Mat mat; 86d7c1e57SBarry Smith Vec work; 96d7c1e57SBarry Smith Mat_CompositeLink next, prev; 10793850ffSBarry Smith }; 11793850ffSBarry Smith 12793850ffSBarry Smith typedef struct { 136d7c1e57SBarry Smith MatCompositeType type; 146d7c1e57SBarry Smith Mat_CompositeLink head, tail; 15793850ffSBarry Smith Vec work; 16e4fc5df0SBarry Smith PetscScalar scale; /* scale factor supplied with MatScale() */ 17e4fc5df0SBarry Smith Vec left, right; /* left and right diagonal scaling provided with MatDiagonalScale() */ 1803049c21SJunchao Zhang Vec leftwork, rightwork, leftwork2, rightwork2; /* Two pairs of working vectors */ 196a7ede75SJakub Kruzik PetscInt nmat; 204b2558d6SJakub Kruzik PetscBool merge; 218c8613bfSJakub Kruzik MatCompositeMergeType mergetype; 223b35acafSJakub Kruzik MatStructure structure; 2303049c21SJunchao Zhang 2403049c21SJunchao Zhang PetscScalar *scalings; 2503049c21SJunchao Zhang PetscBool merge_mvctx; /* Whether need to merge mvctx of component matrices */ 2603049c21SJunchao Zhang Vec *lvecs; /* [nmat] Basically, they are Mvctx->lvec of each component matrix */ 2703049c21SJunchao Zhang PetscScalar *larray; /* [len] Data arrays of lvecs[] are stored consecutively in larray */ 2803049c21SJunchao Zhang PetscInt len; /* Length of larray[] */ 2903049c21SJunchao Zhang Vec gvec; /* Union of lvecs[] without duplicated entries */ 3003049c21SJunchao Zhang PetscInt *location; /* A map that maps entries in garray[] to larray[] */ 3103049c21SJunchao Zhang VecScatter Mvctx; 32793850ffSBarry Smith } Mat_Composite; 33793850ffSBarry Smith 3466976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_Composite(Mat mat) 35d71ae5a4SJacob Faibussowitsch { 362c33bbaeSSatish Balay Mat_Composite *shell = (Mat_Composite *)mat->data; 376d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, oldnext; 3803049c21SJunchao Zhang PetscInt i; 39793850ffSBarry Smith 40793850ffSBarry Smith PetscFunctionBegin; 41793850ffSBarry Smith while (next) { 429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&next->mat)); 4348a46eb9SPierre Jolivet if (next->work && (!next->next || next->work != next->next->work)) PetscCall(VecDestroy(&next->work)); 446d7c1e57SBarry Smith oldnext = next; 45793850ffSBarry Smith next = next->next; 469566063dSJacob Faibussowitsch PetscCall(PetscFree(oldnext)); 47793850ffSBarry Smith } 489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->work)); 499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->left)); 509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->right)); 519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->leftwork)); 529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->rightwork)); 539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->leftwork2)); 549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->rightwork2)); 5503049c21SJunchao Zhang 5603049c21SJunchao Zhang if (shell->Mvctx) { 579566063dSJacob Faibussowitsch for (i = 0; i < shell->nmat; i++) PetscCall(VecDestroy(&shell->lvecs[i])); 589566063dSJacob Faibussowitsch PetscCall(PetscFree3(shell->location, shell->larray, shell->lvecs)); 599566063dSJacob Faibussowitsch PetscCall(PetscFree(shell->larray)); 609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shell->gvec)); 619566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&shell->Mvctx)); 6203049c21SJunchao Zhang } 6303049c21SJunchao Zhang 649566063dSJacob Faibussowitsch PetscCall(PetscFree(shell->scalings)); 652e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeAddMat_C", NULL)); 662e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeSetType_C", NULL)); 672e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeGetType_C", NULL)); 682e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeSetMergeType_C", NULL)); 692e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeSetMatStructure_C", NULL)); 702e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeGetMatStructure_C", NULL)); 712e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeMerge_C", NULL)); 722e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeGetNumberMat_C", NULL)); 732e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeGetMat_C", NULL)); 742e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatCompositeSetScalings_C", NULL)); 759566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->data)); 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77793850ffSBarry Smith } 78793850ffSBarry Smith 7966976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_Composite_Multiplicative(Mat A, Vec x, Vec y) 80d71ae5a4SJacob Faibussowitsch { 816d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite *)A->data; 826d7c1e57SBarry Smith Mat_CompositeLink next = shell->head; 836d7c1e57SBarry Smith Vec in, out; 8403049c21SJunchao Zhang PetscScalar scale; 8503049c21SJunchao Zhang PetscInt i; 866d7c1e57SBarry Smith 876d7c1e57SBarry Smith PetscFunctionBegin; 8828b400f6SJacob Faibussowitsch PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 896d7c1e57SBarry Smith in = x; 90e4fc5df0SBarry Smith if (shell->right) { 9148a46eb9SPierre Jolivet if (!shell->rightwork) PetscCall(VecDuplicate(shell->right, &shell->rightwork)); 929566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(shell->rightwork, shell->right, in)); 93e4fc5df0SBarry Smith in = shell->rightwork; 94e4fc5df0SBarry Smith } 956d7c1e57SBarry Smith while (next->next) { 966d7c1e57SBarry Smith if (!next->work) { /* should reuse previous work if the same size */ 979566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(next->mat, NULL, &next->work)); 986d7c1e57SBarry Smith } 996d7c1e57SBarry Smith out = next->work; 1009566063dSJacob Faibussowitsch PetscCall(MatMult(next->mat, in, out)); 1016d7c1e57SBarry Smith in = out; 1026d7c1e57SBarry Smith next = next->next; 1036d7c1e57SBarry Smith } 1049566063dSJacob Faibussowitsch PetscCall(MatMult(next->mat, in, y)); 1051baa6e33SBarry Smith if (shell->left) PetscCall(VecPointwiseMult(y, shell->left, y)); 10603049c21SJunchao Zhang scale = shell->scale; 1079371c9d4SSatish Balay if (shell->scalings) { 1089371c9d4SSatish Balay for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i]; 1099371c9d4SSatish Balay } 1109566063dSJacob Faibussowitsch PetscCall(VecScale(y, scale)); 1113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1126d7c1e57SBarry Smith } 1136d7c1e57SBarry Smith 11466976f2fSJacob Faibussowitsch static PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A, Vec x, Vec y) 115d71ae5a4SJacob Faibussowitsch { 1166d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite *)A->data; 1176d7c1e57SBarry Smith Mat_CompositeLink tail = shell->tail; 1186d7c1e57SBarry Smith Vec in, out; 11903049c21SJunchao Zhang PetscScalar scale; 12003049c21SJunchao Zhang PetscInt i; 1216d7c1e57SBarry Smith 1226d7c1e57SBarry Smith PetscFunctionBegin; 12328b400f6SJacob Faibussowitsch PetscCheck(tail, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 1246d7c1e57SBarry Smith in = x; 125e4fc5df0SBarry Smith if (shell->left) { 12648a46eb9SPierre Jolivet if (!shell->leftwork) PetscCall(VecDuplicate(shell->left, &shell->leftwork)); 1279566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(shell->leftwork, shell->left, in)); 128e4fc5df0SBarry Smith in = shell->leftwork; 129e4fc5df0SBarry Smith } 1306d7c1e57SBarry Smith while (tail->prev) { 1316d7c1e57SBarry Smith if (!tail->prev->work) { /* should reuse previous work if the same size */ 1329566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(tail->mat, NULL, &tail->prev->work)); 1336d7c1e57SBarry Smith } 1346d7c1e57SBarry Smith out = tail->prev->work; 1359566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(tail->mat, in, out)); 1366d7c1e57SBarry Smith in = out; 1376d7c1e57SBarry Smith tail = tail->prev; 1386d7c1e57SBarry Smith } 1399566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(tail->mat, in, y)); 1401baa6e33SBarry Smith if (shell->right) PetscCall(VecPointwiseMult(y, shell->right, y)); 14103049c21SJunchao Zhang 14203049c21SJunchao Zhang scale = shell->scale; 1439371c9d4SSatish Balay if (shell->scalings) { 1449371c9d4SSatish Balay for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i]; 1459371c9d4SSatish Balay } 1469566063dSJacob Faibussowitsch PetscCall(VecScale(y, scale)); 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1486d7c1e57SBarry Smith } 1496d7c1e57SBarry Smith 15066976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_Composite(Mat mat, Vec x, Vec y) 151d71ae5a4SJacob Faibussowitsch { 15203049c21SJunchao Zhang Mat_Composite *shell = (Mat_Composite *)mat->data; 15303049c21SJunchao Zhang Mat_CompositeLink cur = shell->head; 15403049c21SJunchao Zhang Vec in, y2, xin; 15503049c21SJunchao Zhang Mat A, B; 15603049c21SJunchao Zhang PetscInt i, j, k, n, nuniq, lo, hi, mid, *gindices, *buf, *tmp, tot; 15703049c21SJunchao Zhang const PetscScalar *vals; 15803049c21SJunchao Zhang const PetscInt *garray; 15903049c21SJunchao Zhang IS ix, iy; 16003049c21SJunchao Zhang PetscBool match; 161793850ffSBarry Smith 162793850ffSBarry Smith PetscFunctionBegin; 16328b400f6SJacob Faibussowitsch PetscCheck(cur, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 164e4fc5df0SBarry Smith in = x; 165e4fc5df0SBarry Smith if (shell->right) { 16648a46eb9SPierre Jolivet if (!shell->rightwork) PetscCall(VecDuplicate(shell->right, &shell->rightwork)); 1679566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(shell->rightwork, shell->right, in)); 168e4fc5df0SBarry Smith in = shell->rightwork; 169e4fc5df0SBarry Smith } 17003049c21SJunchao Zhang 17103049c21SJunchao Zhang /* Try to merge Mvctx when instructed but not yet done. We did not do it in MatAssemblyEnd() since at that time 17203049c21SJunchao Zhang we did not know whether mat is ADDITIVE or MULTIPLICATIVE. Only now we are assured mat is ADDITIVE and 17303049c21SJunchao Zhang it is legal to merge Mvctx, because all component matrices have the same size. 17403049c21SJunchao Zhang */ 17503049c21SJunchao Zhang if (shell->merge_mvctx && !shell->Mvctx) { 17603049c21SJunchao Zhang /* Currently only implemented for MATMPIAIJ */ 17703049c21SJunchao Zhang for (cur = shell->head; cur; cur = cur->next) { 1789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)cur->mat, MATMPIAIJ, &match)); 17903049c21SJunchao Zhang if (!match) { 18003049c21SJunchao Zhang shell->merge_mvctx = PETSC_FALSE; 18103049c21SJunchao Zhang goto skip_merge_mvctx; 182e4fc5df0SBarry Smith } 183e4fc5df0SBarry Smith } 18403049c21SJunchao Zhang 18503049c21SJunchao Zhang /* Go through matrices first time to count total number of nonzero off-diag columns (may have dups) */ 18603049c21SJunchao Zhang tot = 0; 18703049c21SJunchao Zhang for (cur = shell->head; cur; cur = cur->next) { 1889566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, NULL)); 1899566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B, NULL, &n)); 19003049c21SJunchao Zhang tot += n; 19103049c21SJunchao Zhang } 1929566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(tot, &shell->location, tot, &shell->larray, shell->nmat, &shell->lvecs)); 19303049c21SJunchao Zhang shell->len = tot; 19403049c21SJunchao Zhang 19503049c21SJunchao Zhang /* Go through matrices second time to sort off-diag columns and remove dups */ 1969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tot, &gindices)); /* No Malloc2() since we will give one to petsc and free the other */ 1979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tot, &buf)); 19803049c21SJunchao Zhang nuniq = 0; /* Number of unique nonzero columns */ 19903049c21SJunchao Zhang for (cur = shell->head; cur; cur = cur->next) { 2009566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, &garray)); 2019566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B, NULL, &n)); 20203049c21SJunchao Zhang /* Merge pre-sorted garray[0,n) and gindices[0,nuniq) to buf[] */ 20303049c21SJunchao Zhang i = j = k = 0; 20403049c21SJunchao Zhang while (i < n && j < nuniq) { 20503049c21SJunchao Zhang if (garray[i] < gindices[j]) buf[k++] = garray[i++]; 20603049c21SJunchao Zhang else if (garray[i] > gindices[j]) buf[k++] = gindices[j++]; 2079371c9d4SSatish Balay else { 2089371c9d4SSatish Balay buf[k++] = garray[i++]; 2099371c9d4SSatish Balay j++; 2109371c9d4SSatish Balay } 21103049c21SJunchao Zhang } 21203049c21SJunchao Zhang /* Copy leftover in garray[] or gindices[] */ 21303049c21SJunchao Zhang if (i < n) { 2149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(buf + k, garray + i, n - i)); 21503049c21SJunchao Zhang nuniq = k + n - i; 21603049c21SJunchao Zhang } else if (j < nuniq) { 2179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(buf + k, gindices + j, nuniq - j)); 21803049c21SJunchao Zhang nuniq = k + nuniq - j; 21903049c21SJunchao Zhang } else nuniq = k; 22003049c21SJunchao Zhang /* Swap gindices and buf to merge garray of the next matrix */ 22103049c21SJunchao Zhang tmp = gindices; 22203049c21SJunchao Zhang gindices = buf; 22303049c21SJunchao Zhang buf = tmp; 22403049c21SJunchao Zhang } 2259566063dSJacob Faibussowitsch PetscCall(PetscFree(buf)); 22603049c21SJunchao Zhang 22703049c21SJunchao Zhang /* Go through matrices third time to build a map from gindices[] to garray[] */ 22803049c21SJunchao Zhang tot = 0; 22903049c21SJunchao Zhang for (cur = shell->head, j = 0; cur; cur = cur->next, j++) { /* j-th matrix */ 2309566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, &garray)); 2319566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B, NULL, &n)); 2329566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, n, NULL, &shell->lvecs[j])); 23303049c21SJunchao Zhang /* This is an optimized PetscFindInt(garray[i],nuniq,gindices,&shell->location[tot+i]), using the fact that garray[] is also sorted */ 23403049c21SJunchao Zhang lo = 0; 23503049c21SJunchao Zhang for (i = 0; i < n; i++) { 23603049c21SJunchao Zhang hi = nuniq; 23703049c21SJunchao Zhang while (hi - lo > 1) { 23803049c21SJunchao Zhang mid = lo + (hi - lo) / 2; 23903049c21SJunchao Zhang if (garray[i] < gindices[mid]) hi = mid; 24003049c21SJunchao Zhang else lo = mid; 24103049c21SJunchao Zhang } 24203049c21SJunchao Zhang shell->location[tot + i] = lo; /* gindices[lo] = garray[i] */ 24303049c21SJunchao Zhang lo++; /* Since garray[i+1] > garray[i], we can safely advance lo */ 24403049c21SJunchao Zhang } 24503049c21SJunchao Zhang tot += n; 24603049c21SJunchao Zhang } 24703049c21SJunchao Zhang 24803049c21SJunchao Zhang /* Build merged Mvctx */ 2499566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nuniq, gindices, PETSC_OWN_POINTER, &ix)); 2509566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nuniq, 0, 1, &iy)); 2519566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)mat), 1, mat->cmap->n, mat->cmap->N, NULL, &xin)); 2529566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, nuniq, &shell->gvec)); 2539566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(xin, ix, shell->gvec, iy, &shell->Mvctx)); 2549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xin)); 2559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ix)); 2569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iy)); 25703049c21SJunchao Zhang } 25803049c21SJunchao Zhang 25903049c21SJunchao Zhang skip_merge_mvctx: 2609566063dSJacob Faibussowitsch PetscCall(VecSet(y, 0)); 2619566063dSJacob Faibussowitsch if (!shell->leftwork2) PetscCall(VecDuplicate(y, &shell->leftwork2)); 26203049c21SJunchao Zhang y2 = shell->leftwork2; 26303049c21SJunchao Zhang 26403049c21SJunchao Zhang if (shell->Mvctx) { /* Have a merged Mvctx */ 26503049c21SJunchao Zhang /* Suppose we want to compute y = sMx, where s is the scaling factor and A, B are matrix M's diagonal/off-diagonal part. We could do 266da81f932SPierre Jolivet in y = s(Ax1 + Bx2) or y = sAx1 + sBx2. The former incurs less FLOPS than the latter, but the latter provides an opportunity to 26703049c21SJunchao Zhang overlap communication/computation since we can do sAx1 while communicating x2. Here, we use the former approach. 26803049c21SJunchao Zhang */ 2699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(shell->Mvctx, in, shell->gvec, INSERT_VALUES, SCATTER_FORWARD)); 2709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(shell->Mvctx, in, shell->gvec, INSERT_VALUES, SCATTER_FORWARD)); 27103049c21SJunchao Zhang 2729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shell->gvec, &vals)); 27303049c21SJunchao Zhang for (i = 0; i < shell->len; i++) shell->larray[i] = vals[shell->location[i]]; 2749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shell->gvec, &vals)); 27503049c21SJunchao Zhang 27603049c21SJunchao Zhang for (cur = shell->head, tot = i = 0; cur; cur = cur->next, i++) { /* i-th matrix */ 2779566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, &A, &B, NULL)); 278dbbe0bcdSBarry Smith PetscUseTypeMethod(A, mult, in, y2); 2799566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B, NULL, &n)); 2809566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(shell->lvecs[i], &shell->larray[tot])); 2819566063dSJacob Faibussowitsch PetscCall((*B->ops->multadd)(B, shell->lvecs[i], y2, y2)); 2829566063dSJacob Faibussowitsch PetscCall(VecResetArray(shell->lvecs[i])); 2839566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, (shell->scalings ? shell->scalings[i] : 1.0), y2)); 28403049c21SJunchao Zhang tot += n; 28503049c21SJunchao Zhang } 28603049c21SJunchao Zhang } else { 28703049c21SJunchao Zhang if (shell->scalings) { 28803049c21SJunchao Zhang for (cur = shell->head, i = 0; cur; cur = cur->next, i++) { 2899566063dSJacob Faibussowitsch PetscCall(MatMult(cur->mat, in, y2)); 2909566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, shell->scalings[i], y2)); 29103049c21SJunchao Zhang } 29203049c21SJunchao Zhang } else { 2939566063dSJacob Faibussowitsch for (cur = shell->head; cur; cur = cur->next) PetscCall(MatMultAdd(cur->mat, in, y, y)); 29403049c21SJunchao Zhang } 29503049c21SJunchao Zhang } 29603049c21SJunchao Zhang 2979566063dSJacob Faibussowitsch if (shell->left) PetscCall(VecPointwiseMult(y, shell->left, y)); 2989566063dSJacob Faibussowitsch PetscCall(VecScale(y, shell->scale)); 2993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 300793850ffSBarry Smith } 301793850ffSBarry Smith 30266976f2fSJacob Faibussowitsch static PetscErrorCode MatMultTranspose_Composite(Mat A, Vec x, Vec y) 303d71ae5a4SJacob Faibussowitsch { 304793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite *)A->data; 305793850ffSBarry Smith Mat_CompositeLink next = shell->head; 30603049c21SJunchao Zhang Vec in, y2 = NULL; 30703049c21SJunchao Zhang PetscInt i; 308793850ffSBarry Smith 309793850ffSBarry Smith PetscFunctionBegin; 31028b400f6SJacob Faibussowitsch PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 311e4fc5df0SBarry Smith in = x; 312e4fc5df0SBarry Smith if (shell->left) { 31348a46eb9SPierre Jolivet if (!shell->leftwork) PetscCall(VecDuplicate(shell->left, &shell->leftwork)); 3149566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(shell->leftwork, shell->left, in)); 315e4fc5df0SBarry Smith in = shell->leftwork; 316e4fc5df0SBarry Smith } 31703049c21SJunchao Zhang 3189566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(next->mat, in, y)); 31903049c21SJunchao Zhang if (shell->scalings) { 3209566063dSJacob Faibussowitsch PetscCall(VecScale(y, shell->scalings[0])); 3219566063dSJacob Faibussowitsch if (!shell->rightwork2) PetscCall(VecDuplicate(y, &shell->rightwork2)); 32203049c21SJunchao Zhang y2 = shell->rightwork2; 32303049c21SJunchao Zhang } 32403049c21SJunchao Zhang i = 1; 325e4fc5df0SBarry Smith while ((next = next->next)) { 3269566063dSJacob Faibussowitsch if (!shell->scalings) PetscCall(MatMultTransposeAdd(next->mat, in, y, y)); 32703049c21SJunchao Zhang else { 3289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(next->mat, in, y2)); 3299566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, shell->scalings[i++], y2)); 33003049c21SJunchao Zhang } 331e4fc5df0SBarry Smith } 3321baa6e33SBarry Smith if (shell->right) PetscCall(VecPointwiseMult(y, shell->right, y)); 3339566063dSJacob Faibussowitsch PetscCall(VecScale(y, shell->scale)); 3343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 335793850ffSBarry Smith } 336793850ffSBarry Smith 33766976f2fSJacob Faibussowitsch static PetscErrorCode MatMultAdd_Composite(Mat A, Vec x, Vec y, Vec z) 338d71ae5a4SJacob Faibussowitsch { 3397bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite *)A->data; 3407bf3a71bSJakub Kruzik 3417bf3a71bSJakub Kruzik PetscFunctionBegin; 3427bf3a71bSJakub Kruzik if (y != z) { 3439566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, z)); 3449566063dSJacob Faibussowitsch PetscCall(VecAXPY(z, 1.0, y)); 3457bf3a71bSJakub Kruzik } else { 34648a46eb9SPierre Jolivet if (!shell->leftwork) PetscCall(VecDuplicate(z, &shell->leftwork)); 3479566063dSJacob Faibussowitsch PetscCall(MatMult(A, x, shell->leftwork)); 3489566063dSJacob Faibussowitsch PetscCall(VecCopy(y, z)); 3499566063dSJacob Faibussowitsch PetscCall(VecAXPY(z, 1.0, shell->leftwork)); 3507bf3a71bSJakub Kruzik } 3513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3527bf3a71bSJakub Kruzik } 3537bf3a71bSJakub Kruzik 35466976f2fSJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_Composite(Mat A, Vec x, Vec y, Vec z) 355d71ae5a4SJacob Faibussowitsch { 3567bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite *)A->data; 3577bf3a71bSJakub Kruzik 3587bf3a71bSJakub Kruzik PetscFunctionBegin; 3597bf3a71bSJakub Kruzik if (y != z) { 3609566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, x, z)); 3619566063dSJacob Faibussowitsch PetscCall(VecAXPY(z, 1.0, y)); 3627bf3a71bSJakub Kruzik } else { 36348a46eb9SPierre Jolivet if (!shell->rightwork) PetscCall(VecDuplicate(z, &shell->rightwork)); 3649566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, x, shell->rightwork)); 3659566063dSJacob Faibussowitsch PetscCall(VecCopy(y, z)); 3669566063dSJacob Faibussowitsch PetscCall(VecAXPY(z, 1.0, shell->rightwork)); 3677bf3a71bSJakub Kruzik } 3683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3697bf3a71bSJakub Kruzik } 3707bf3a71bSJakub Kruzik 37166976f2fSJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_Composite(Mat A, Vec v) 372d71ae5a4SJacob Faibussowitsch { 373793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite *)A->data; 374793850ffSBarry Smith Mat_CompositeLink next = shell->head; 37503049c21SJunchao Zhang PetscInt i; 376793850ffSBarry Smith 377793850ffSBarry Smith PetscFunctionBegin; 37828b400f6SJacob Faibussowitsch PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 37908401ef6SPierre Jolivet PetscCheck(!shell->right && !shell->left, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get diagonal if left or right scaling"); 380e4fc5df0SBarry Smith 3819566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(next->mat, v)); 3829566063dSJacob Faibussowitsch if (shell->scalings) PetscCall(VecScale(v, shell->scalings[0])); 38303049c21SJunchao Zhang 38448a46eb9SPierre Jolivet if (next->next && !shell->work) PetscCall(VecDuplicate(v, &shell->work)); 38503049c21SJunchao Zhang i = 1; 386793850ffSBarry Smith while ((next = next->next)) { 3879566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(next->mat, shell->work)); 3889566063dSJacob Faibussowitsch PetscCall(VecAXPY(v, (shell->scalings ? shell->scalings[i++] : 1.0), shell->work)); 389793850ffSBarry Smith } 3909566063dSJacob Faibussowitsch PetscCall(VecScale(v, shell->scale)); 3913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 392793850ffSBarry Smith } 393793850ffSBarry Smith 39466976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_Composite(Mat Y, MatAssemblyType t) 395d71ae5a4SJacob Faibussowitsch { 3964b2558d6SJakub Kruzik Mat_Composite *shell = (Mat_Composite *)Y->data; 397b52f573bSBarry Smith 398793850ffSBarry Smith PetscFunctionBegin; 3991baa6e33SBarry Smith if (shell->merge) PetscCall(MatCompositeMerge(Y)); 4003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 401793850ffSBarry Smith } 402793850ffSBarry Smith 40366976f2fSJacob Faibussowitsch static PetscErrorCode MatScale_Composite(Mat inA, PetscScalar alpha) 404d71ae5a4SJacob Faibussowitsch { 405e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite *)inA->data; 406e4fc5df0SBarry Smith 407e4fc5df0SBarry Smith PetscFunctionBegin; 408321429dbSBarry Smith a->scale *= alpha; 4093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 410e4fc5df0SBarry Smith } 411e4fc5df0SBarry Smith 41266976f2fSJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_Composite(Mat inA, Vec left, Vec right) 413d71ae5a4SJacob Faibussowitsch { 414e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite *)inA->data; 415e4fc5df0SBarry Smith 416e4fc5df0SBarry Smith PetscFunctionBegin; 417e4fc5df0SBarry Smith if (left) { 418321429dbSBarry Smith if (!a->left) { 4199566063dSJacob Faibussowitsch PetscCall(VecDuplicate(left, &a->left)); 4209566063dSJacob Faibussowitsch PetscCall(VecCopy(left, a->left)); 421321429dbSBarry Smith } else { 4229566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(a->left, left, a->left)); 423321429dbSBarry Smith } 424e4fc5df0SBarry Smith } 425e4fc5df0SBarry Smith if (right) { 426321429dbSBarry Smith if (!a->right) { 4279566063dSJacob Faibussowitsch PetscCall(VecDuplicate(right, &a->right)); 4289566063dSJacob Faibussowitsch PetscCall(VecCopy(right, a->right)); 429321429dbSBarry Smith } else { 4309566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(a->right, right, a->right)); 431321429dbSBarry Smith } 432e4fc5df0SBarry Smith } 4333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 434e4fc5df0SBarry Smith } 435793850ffSBarry Smith 43666976f2fSJacob Faibussowitsch static PetscErrorCode MatSetFromOptions_Composite(Mat A, PetscOptionItems *PetscOptionsObject) 437d71ae5a4SJacob Faibussowitsch { 4384b2558d6SJakub Kruzik Mat_Composite *a = (Mat_Composite *)A->data; 4394b2558d6SJakub Kruzik 4404b2558d6SJakub Kruzik PetscFunctionBegin; 441d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATCOMPOSITE options"); 4429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_composite_merge", "Merge at MatAssemblyEnd", "MatCompositeMerge", a->merge, &a->merge, NULL)); 4439566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-mat_composite_merge_type", "Set composite merge direction", "MatCompositeSetMergeType", MatCompositeMergeTypes, (PetscEnum)a->mergetype, (PetscEnum *)&a->mergetype, NULL)); 4449566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_composite_merge_mvctx", "Merge MatMult() vecscat contexts", "MatCreateComposite", a->merge_mvctx, &a->merge_mvctx, NULL)); 445d0609cedSBarry Smith PetscOptionsHeadEnd(); 4463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4474b2558d6SJakub Kruzik } 4484b2558d6SJakub Kruzik 4492c0821f3SBarry Smith /*@ 4508bd739bdSJakub Kruzik MatCreateComposite - Creates a matrix as the sum or product of one or more matrices 451793850ffSBarry Smith 452d083f849SBarry Smith Collective 453793850ffSBarry Smith 454793850ffSBarry Smith Input Parameters: 455793850ffSBarry Smith + comm - MPI communicator 456793850ffSBarry Smith . nmat - number of matrices to put in 457793850ffSBarry Smith - mats - the matrices 458793850ffSBarry Smith 459793850ffSBarry Smith Output Parameter: 460db36af27SMatthew G. Knepley . mat - the matrix 461793850ffSBarry Smith 4624b2558d6SJakub Kruzik Options Database Keys: 46311a5261eSBarry Smith + -mat_composite_merge - merge in `MatAssemblyEnd()` 46411a5261eSBarry Smith . -mat_composite_merge_mvctx - merge Mvctx of component matrices to optimize communication in `MatMult()` for ADDITIVE matrices 465b28d0daaSJakub Kruzik - -mat_composite_merge_type - set merge direction 4664b2558d6SJakub Kruzik 467793850ffSBarry Smith Level: advanced 468793850ffSBarry Smith 46911a5261eSBarry Smith Note: 470793850ffSBarry Smith Alternative construction 4712ef1f0ffSBarry Smith .vb 4722ef1f0ffSBarry Smith MatCreate(comm,&mat); 4732ef1f0ffSBarry Smith MatSetSizes(mat,m,n,M,N); 4742ef1f0ffSBarry Smith MatSetType(mat,MATCOMPOSITE); 4752ef1f0ffSBarry Smith MatCompositeAddMat(mat,mats[0]); 4762ef1f0ffSBarry Smith .... 4772ef1f0ffSBarry Smith MatCompositeAddMat(mat,mats[nmat-1]); 4782ef1f0ffSBarry Smith MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); 4792ef1f0ffSBarry Smith MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); 4802ef1f0ffSBarry Smith .ve 481793850ffSBarry Smith 4826d7c1e57SBarry Smith For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] 4836d7c1e57SBarry Smith 4841cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCompositeGetMat()`, `MatCompositeMerge()`, `MatCompositeSetType()`, 48520f4b53cSBarry Smith `MATCOMPOSITE`, `MatCompositeType` 486793850ffSBarry Smith @*/ 487d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateComposite(MPI_Comm comm, PetscInt nmat, const Mat *mats, Mat *mat) 488d71ae5a4SJacob Faibussowitsch { 489793850ffSBarry Smith PetscInt m, n, M, N, i; 490793850ffSBarry Smith 491793850ffSBarry Smith PetscFunctionBegin; 49208401ef6SPierre Jolivet PetscCheck(nmat >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must pass in at least one matrix"); 4934f572ea9SToby Isaac PetscAssertPointer(mat, 4); 494793850ffSBarry Smith 4959566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mats[0], PETSC_IGNORE, &n)); 4969566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mats[nmat - 1], &m, PETSC_IGNORE)); 4979566063dSJacob Faibussowitsch PetscCall(MatGetSize(mats[0], PETSC_IGNORE, &N)); 4989566063dSJacob Faibussowitsch PetscCall(MatGetSize(mats[nmat - 1], &M, PETSC_IGNORE)); 4999566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, mat)); 5009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, m, n, M, N)); 5019566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat, MATCOMPOSITE)); 50248a46eb9SPierre Jolivet for (i = 0; i < nmat; i++) PetscCall(MatCompositeAddMat(*mat, mats[i])); 5039566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 5049566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 5053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 506793850ffSBarry Smith } 507793850ffSBarry Smith 508d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeAddMat_Composite(Mat mat, Mat smat) 509d71ae5a4SJacob Faibussowitsch { 510d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite *)mat->data; 511d7f81bf2SJakub Kruzik Mat_CompositeLink ilink, next = shell->head; 512*5c8dc79eSRichard Tran Mills VecType vtype_mat, vtype_smat; 513*5c8dc79eSRichard Tran Mills PetscBool match; 514d7f81bf2SJakub Kruzik 515d7f81bf2SJakub Kruzik PetscFunctionBegin; 5164dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ilink)); 517f4259b30SLisandro Dalcin ilink->next = NULL; 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)smat)); 519d7f81bf2SJakub Kruzik ilink->mat = smat; 520d7f81bf2SJakub Kruzik 521d7f81bf2SJakub Kruzik if (!next) shell->head = ilink; 522d7f81bf2SJakub Kruzik else { 523ad540459SPierre Jolivet while (next->next) next = next->next; 524d7f81bf2SJakub Kruzik next->next = ilink; 525d7f81bf2SJakub Kruzik ilink->prev = next; 526d7f81bf2SJakub Kruzik } 527d7f81bf2SJakub Kruzik shell->tail = ilink; 528d7f81bf2SJakub Kruzik shell->nmat += 1; 52903049c21SJunchao Zhang 530*5c8dc79eSRichard Tran Mills /* If all of the partial matrices have the same default vector type, then the composite matrix should also have this default type. 531*5c8dc79eSRichard Tran Mills Otherwise, the default type should be "standard". */ 532*5c8dc79eSRichard Tran Mills PetscCall(MatGetVecType(smat, &vtype_smat)); 533*5c8dc79eSRichard Tran Mills if (shell->nmat == 1) PetscCall(MatSetVecType(mat, vtype_smat)); 534*5c8dc79eSRichard Tran Mills else { 535*5c8dc79eSRichard Tran Mills PetscCall(MatGetVecType(mat, &vtype_mat)); 536*5c8dc79eSRichard Tran Mills PetscCall(PetscStrcmp(vtype_smat, vtype_mat, &match)); 537*5c8dc79eSRichard Tran Mills if (!match) PetscCall(MatSetVecType(mat, VECSTANDARD)); 538*5c8dc79eSRichard Tran Mills } 539*5c8dc79eSRichard Tran Mills 54003049c21SJunchao Zhang /* Retain the old scalings (if any) and expand it with a 1.0 for the newly added matrix */ 54103049c21SJunchao Zhang if (shell->scalings) { 5429566063dSJacob Faibussowitsch PetscCall(PetscRealloc(sizeof(PetscScalar) * shell->nmat, &shell->scalings)); 54303049c21SJunchao Zhang shell->scalings[shell->nmat - 1] = 1.0; 54403049c21SJunchao Zhang } 5453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546d7f81bf2SJakub Kruzik } 547d7f81bf2SJakub Kruzik 548793850ffSBarry Smith /*@ 5498bd739bdSJakub Kruzik MatCompositeAddMat - Add another matrix to a composite matrix. 550793850ffSBarry Smith 551c3339decSBarry Smith Collective 552793850ffSBarry Smith 553793850ffSBarry Smith Input Parameters: 554793850ffSBarry Smith + mat - the composite matrix 555793850ffSBarry Smith - smat - the partial matrix 556793850ffSBarry Smith 557793850ffSBarry Smith Level: advanced 558793850ffSBarry Smith 5591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeGetMat()`, `MATCOMPOSITE` 560793850ffSBarry Smith @*/ 561d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeAddMat(Mat mat, Mat smat) 562d71ae5a4SJacob Faibussowitsch { 563793850ffSBarry Smith PetscFunctionBegin; 5640700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5650700a824SBarry Smith PetscValidHeaderSpecific(smat, MAT_CLASSID, 2); 566cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeAddMat_C", (Mat, Mat), (mat, smat)); 5673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 568d7f81bf2SJakub Kruzik } 569793850ffSBarry Smith 570d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeSetType_Composite(Mat mat, MatCompositeType type) 571d71ae5a4SJacob Faibussowitsch { 572d7f81bf2SJakub Kruzik Mat_Composite *b = (Mat_Composite *)mat->data; 573d7f81bf2SJakub Kruzik 574d7f81bf2SJakub Kruzik PetscFunctionBegin; 575ced1ac25SJakub Kruzik b->type = type; 576d7f81bf2SJakub Kruzik if (type == MAT_COMPOSITE_MULTIPLICATIVE) { 577f4259b30SLisandro Dalcin mat->ops->getdiagonal = NULL; 578d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite_Multiplicative; 579d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; 58003049c21SJunchao Zhang b->merge_mvctx = PETSC_FALSE; 581d7f81bf2SJakub Kruzik } else { 582d7f81bf2SJakub Kruzik mat->ops->getdiagonal = MatGetDiagonal_Composite; 583d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite; 584d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite; 585793850ffSBarry Smith } 5863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5876d7c1e57SBarry Smith } 5886d7c1e57SBarry Smith 5892c0821f3SBarry Smith /*@ 5908bd739bdSJakub Kruzik MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product. 5916d7c1e57SBarry Smith 592c3339decSBarry Smith Logically Collective 5936d7c1e57SBarry Smith 5946d7c1e57SBarry Smith Input Parameters: 59520f4b53cSBarry Smith + mat - the composite matrix 59620f4b53cSBarry Smith - type - the `MatCompositeType` to use for the matrix 5976d7c1e57SBarry Smith 5986d7c1e57SBarry Smith Level: advanced 5996d7c1e57SBarry Smith 6001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCreateComposite()`, `MatCompositeGetType()`, `MATCOMPOSITE`, 60120f4b53cSBarry Smith `MatCompositeType` 6026d7c1e57SBarry Smith @*/ 603d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeSetType(Mat mat, MatCompositeType type) 604d71ae5a4SJacob Faibussowitsch { 6056d7c1e57SBarry Smith PetscFunctionBegin; 606d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 607b2b245abSJakub Kruzik PetscValidLogicalCollectiveEnum(mat, type, 2); 608cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeSetType_C", (Mat, MatCompositeType), (mat, type)); 6093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 610793850ffSBarry Smith } 611793850ffSBarry Smith 612d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeGetType_Composite(Mat mat, MatCompositeType *type) 613d71ae5a4SJacob Faibussowitsch { 6146dbc55e5SJakub Kruzik Mat_Composite *b = (Mat_Composite *)mat->data; 6156dbc55e5SJakub Kruzik 6166dbc55e5SJakub Kruzik PetscFunctionBegin; 6176dbc55e5SJakub Kruzik *type = b->type; 6183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6196dbc55e5SJakub Kruzik } 6206dbc55e5SJakub Kruzik 6216dbc55e5SJakub Kruzik /*@ 6226dbc55e5SJakub Kruzik MatCompositeGetType - Returns type of composite. 6236dbc55e5SJakub Kruzik 6246dbc55e5SJakub Kruzik Not Collective 6256dbc55e5SJakub Kruzik 6266dbc55e5SJakub Kruzik Input Parameter: 6276dbc55e5SJakub Kruzik . mat - the composite matrix 6286dbc55e5SJakub Kruzik 6296dbc55e5SJakub Kruzik Output Parameter: 6306dbc55e5SJakub Kruzik . type - type of composite 6316dbc55e5SJakub Kruzik 6326dbc55e5SJakub Kruzik Level: advanced 6336dbc55e5SJakub Kruzik 6341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeSetType()`, `MATCOMPOSITE`, `MatCompositeType` 6356dbc55e5SJakub Kruzik @*/ 636d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeGetType(Mat mat, MatCompositeType *type) 637d71ae5a4SJacob Faibussowitsch { 6386dbc55e5SJakub Kruzik PetscFunctionBegin; 6396dbc55e5SJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6404f572ea9SToby Isaac PetscAssertPointer(type, 2); 641cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeGetType_C", (Mat, MatCompositeType *), (mat, type)); 6423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6436dbc55e5SJakub Kruzik } 6446dbc55e5SJakub Kruzik 645d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeSetMatStructure_Composite(Mat mat, MatStructure str) 646d71ae5a4SJacob Faibussowitsch { 6473b35acafSJakub Kruzik Mat_Composite *b = (Mat_Composite *)mat->data; 6483b35acafSJakub Kruzik 6493b35acafSJakub Kruzik PetscFunctionBegin; 6503b35acafSJakub Kruzik b->structure = str; 6513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6523b35acafSJakub Kruzik } 6533b35acafSJakub Kruzik 6543b35acafSJakub Kruzik /*@ 6553b35acafSJakub Kruzik MatCompositeSetMatStructure - Indicates structure of matrices in the composite matrix. 6563b35acafSJakub Kruzik 6573b35acafSJakub Kruzik Not Collective 6583b35acafSJakub Kruzik 6593b35acafSJakub Kruzik Input Parameters: 6603b35acafSJakub Kruzik + mat - the composite matrix 66111a5261eSBarry Smith - str - either `SAME_NONZERO_PATTERN`, `DIFFERENT_NONZERO_PATTERN` (default) or `SUBSET_NONZERO_PATTERN` 6623b35acafSJakub Kruzik 6633b35acafSJakub Kruzik Level: advanced 6643b35acafSJakub Kruzik 66511a5261eSBarry Smith Note: 66611a5261eSBarry Smith Information about the matrices structure is used in `MatCompositeMerge()` for additive composite matrix. 6673b35acafSJakub Kruzik 6681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatAXPY()`, `MatCreateComposite()`, `MatCompositeMerge()` `MatCompositeGetMatStructure()`, `MATCOMPOSITE` 6693b35acafSJakub Kruzik @*/ 670d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeSetMatStructure(Mat mat, MatStructure str) 671d71ae5a4SJacob Faibussowitsch { 6723b35acafSJakub Kruzik PetscFunctionBegin; 6733b35acafSJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 674cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeSetMatStructure_C", (Mat, MatStructure), (mat, str)); 6753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6763b35acafSJakub Kruzik } 6773b35acafSJakub Kruzik 678d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeGetMatStructure_Composite(Mat mat, MatStructure *str) 679d71ae5a4SJacob Faibussowitsch { 6803b35acafSJakub Kruzik Mat_Composite *b = (Mat_Composite *)mat->data; 6813b35acafSJakub Kruzik 6823b35acafSJakub Kruzik PetscFunctionBegin; 6833b35acafSJakub Kruzik *str = b->structure; 6843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6853b35acafSJakub Kruzik } 6863b35acafSJakub Kruzik 6873b35acafSJakub Kruzik /*@ 6883b35acafSJakub Kruzik MatCompositeGetMatStructure - Returns the structure of matrices in the composite matrix. 6893b35acafSJakub Kruzik 6903b35acafSJakub Kruzik Not Collective 6913b35acafSJakub Kruzik 6923b35acafSJakub Kruzik Input Parameter: 6933b35acafSJakub Kruzik . mat - the composite matrix 6943b35acafSJakub Kruzik 6953b35acafSJakub Kruzik Output Parameter: 6963b35acafSJakub Kruzik . str - structure of the matrices 6973b35acafSJakub Kruzik 6983b35acafSJakub Kruzik Level: advanced 6993b35acafSJakub Kruzik 7001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeSetMatStructure()`, `MATCOMPOSITE` 7013b35acafSJakub Kruzik @*/ 702d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeGetMatStructure(Mat mat, MatStructure *str) 703d71ae5a4SJacob Faibussowitsch { 7043b35acafSJakub Kruzik PetscFunctionBegin; 7053b35acafSJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7064f572ea9SToby Isaac PetscAssertPointer(str, 2); 707cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeGetMatStructure_C", (Mat, MatStructure *), (mat, str)); 7083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7093b35acafSJakub Kruzik } 7103b35acafSJakub Kruzik 711d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeSetMergeType_Composite(Mat mat, MatCompositeMergeType type) 712d71ae5a4SJacob Faibussowitsch { 7138c8613bfSJakub Kruzik Mat_Composite *shell = (Mat_Composite *)mat->data; 7148c8613bfSJakub Kruzik 7158c8613bfSJakub Kruzik PetscFunctionBegin; 7168c8613bfSJakub Kruzik shell->mergetype = type; 7173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7188c8613bfSJakub Kruzik } 7198c8613bfSJakub Kruzik 7208c8613bfSJakub Kruzik /*@ 72111a5261eSBarry Smith MatCompositeSetMergeType - Sets order of `MatCompositeMerge()`. 7228c8613bfSJakub Kruzik 723c3339decSBarry Smith Logically Collective 7248c8613bfSJakub Kruzik 725d8d19677SJose E. Roman Input Parameters: 7268c8613bfSJakub Kruzik + mat - the composite matrix 72711a5261eSBarry Smith - type - `MAT_COMPOSITE_MERGE RIGHT` (default) to start merge from right with the first added matrix (mat[0]), 72811a5261eSBarry Smith `MAT_COMPOSITE_MERGE_LEFT` to start merge from left with the last added matrix (mat[nmat-1]) 7298c8613bfSJakub Kruzik 7308c8613bfSJakub Kruzik Level: advanced 7318c8613bfSJakub Kruzik 73211a5261eSBarry Smith Note: 733da81f932SPierre Jolivet The resulting matrix is the same regardless of the `MatCompositeMergeType`. Only the order of operation is changed. 73411a5261eSBarry Smith If set to `MAT_COMPOSITE_MERGE_RIGHT` the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0]))) 7358c8613bfSJakub Kruzik otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0]. 7368c8613bfSJakub Kruzik 7371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeMerge()`, `MATCOMPOSITE` 7388c8613bfSJakub Kruzik @*/ 739d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeSetMergeType(Mat mat, MatCompositeMergeType type) 740d71ae5a4SJacob Faibussowitsch { 7418c8613bfSJakub Kruzik PetscFunctionBegin; 7428c8613bfSJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7438c8613bfSJakub Kruzik PetscValidLogicalCollectiveEnum(mat, type, 2); 744cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeSetMergeType_C", (Mat, MatCompositeMergeType), (mat, type)); 7453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7468c8613bfSJakub Kruzik } 7478c8613bfSJakub Kruzik 748d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeMerge_Composite(Mat mat) 749d71ae5a4SJacob Faibussowitsch { 750b52f573bSBarry Smith Mat_Composite *shell = (Mat_Composite *)mat->data; 7516d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, prev = shell->tail; 7526d7c1e57SBarry Smith Mat tmat, newmat; 7531ba60692SJed Brown Vec left, right; 7541ba60692SJed Brown PetscScalar scale; 75503049c21SJunchao Zhang PetscInt i; 756b52f573bSBarry Smith 757b52f573bSBarry Smith PetscFunctionBegin; 75828b400f6SJacob Faibussowitsch PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()"); 75903049c21SJunchao Zhang scale = shell->scale; 7606d7c1e57SBarry Smith if (shell->type == MAT_COMPOSITE_ADDITIVE) { 7618c8613bfSJakub Kruzik if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) { 76203049c21SJunchao Zhang i = 0; 7639566063dSJacob Faibussowitsch PetscCall(MatDuplicate(next->mat, MAT_COPY_VALUES, &tmat)); 7649566063dSJacob Faibussowitsch if (shell->scalings) PetscCall(MatScale(tmat, shell->scalings[i++])); 76548a46eb9SPierre Jolivet while ((next = next->next)) PetscCall(MatAXPY(tmat, (shell->scalings ? shell->scalings[i++] : 1.0), next->mat, shell->structure)); 7666d7c1e57SBarry Smith } else { 76703049c21SJunchao Zhang i = shell->nmat - 1; 7689566063dSJacob Faibussowitsch PetscCall(MatDuplicate(prev->mat, MAT_COPY_VALUES, &tmat)); 7699566063dSJacob Faibussowitsch if (shell->scalings) PetscCall(MatScale(tmat, shell->scalings[i--])); 77048a46eb9SPierre Jolivet while ((prev = prev->prev)) PetscCall(MatAXPY(tmat, (shell->scalings ? shell->scalings[i--] : 1.0), prev->mat, shell->structure)); 7718c8613bfSJakub Kruzik } 7728c8613bfSJakub Kruzik } else { 7738c8613bfSJakub Kruzik if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) { 7749566063dSJacob Faibussowitsch PetscCall(MatDuplicate(next->mat, MAT_COPY_VALUES, &tmat)); 775b6cfcaf5SJakub Kruzik while ((next = next->next)) { 7769566063dSJacob Faibussowitsch PetscCall(MatMatMult(next->mat, tmat, MAT_INITIAL_MATRIX, PETSC_DECIDE, &newmat)); 7779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 7786d7c1e57SBarry Smith tmat = newmat; 7796d7c1e57SBarry Smith } 78004d534ceSJakub Kruzik } else { 7819566063dSJacob Faibussowitsch PetscCall(MatDuplicate(prev->mat, MAT_COPY_VALUES, &tmat)); 78204d534ceSJakub Kruzik while ((prev = prev->prev)) { 7839566063dSJacob Faibussowitsch PetscCall(MatMatMult(tmat, prev->mat, MAT_INITIAL_MATRIX, PETSC_DECIDE, &newmat)); 7849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 78504d534ceSJakub Kruzik tmat = newmat; 78604d534ceSJakub Kruzik } 78704d534ceSJakub Kruzik } 7889371c9d4SSatish Balay if (shell->scalings) { 7899371c9d4SSatish Balay for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i]; 7909371c9d4SSatish Balay } 7916d7c1e57SBarry Smith } 7921ba60692SJed Brown 7939566063dSJacob Faibussowitsch if ((left = shell->left)) PetscCall(PetscObjectReference((PetscObject)left)); 7949566063dSJacob Faibussowitsch if ((right = shell->right)) PetscCall(PetscObjectReference((PetscObject)right)); 7951ba60692SJed Brown 7969566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &tmat)); 7971ba60692SJed Brown 7989566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(mat, left, right)); 7999566063dSJacob Faibussowitsch PetscCall(MatScale(mat, scale)); 8009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&left)); 8019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&right)); 8023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 803b52f573bSBarry Smith } 8046a7ede75SJakub Kruzik 8056a7ede75SJakub Kruzik /*@ 806d7f81bf2SJakub Kruzik MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix 8078bd739bdSJakub Kruzik by summing or computing the product of all the matrices inside the composite matrix. 808d7f81bf2SJakub Kruzik 809b2b245abSJakub Kruzik Collective 810d7f81bf2SJakub Kruzik 811f899ff85SJose E. Roman Input Parameter: 812d7f81bf2SJakub Kruzik . mat - the composite matrix 813d7f81bf2SJakub Kruzik 8144b2558d6SJakub Kruzik Options Database Keys: 81511a5261eSBarry Smith + -mat_composite_merge - merge in `MatAssemblyEnd()` 816b28d0daaSJakub Kruzik - -mat_composite_merge_type - set merge direction 817d7f81bf2SJakub Kruzik 818d7f81bf2SJakub Kruzik Level: advanced 819d7f81bf2SJakub Kruzik 82011a5261eSBarry Smith Note: 82111a5261eSBarry Smith The `MatType` of the resulting matrix will be the same as the `MatType` of the FIRST matrix in the composite matrix. 822d7f81bf2SJakub Kruzik 8231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCreateComposite()`, `MatCompositeSetMatStructure()`, `MatCompositeSetMergeType()`, `MATCOMPOSITE` 824d7f81bf2SJakub Kruzik @*/ 825d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeMerge(Mat mat) 826d71ae5a4SJacob Faibussowitsch { 827d7f81bf2SJakub Kruzik PetscFunctionBegin; 828d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 829cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeMerge_C", (Mat), (mat)); 8303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 831d7f81bf2SJakub Kruzik } 832d7f81bf2SJakub Kruzik 833d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat, PetscInt *nmat) 834d71ae5a4SJacob Faibussowitsch { 835d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite *)mat->data; 836d7f81bf2SJakub Kruzik 837d7f81bf2SJakub Kruzik PetscFunctionBegin; 838d7f81bf2SJakub Kruzik *nmat = shell->nmat; 8393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 840d7f81bf2SJakub Kruzik } 841d7f81bf2SJakub Kruzik 842d7f81bf2SJakub Kruzik /*@ 8436d0add67SJakub Kruzik MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix. 8446a7ede75SJakub Kruzik 8456a7ede75SJakub Kruzik Not Collective 8466a7ede75SJakub Kruzik 8476a7ede75SJakub Kruzik Input Parameter: 848d7f81bf2SJakub Kruzik . mat - the composite matrix 8496a7ede75SJakub Kruzik 8506a7ede75SJakub Kruzik Output Parameter: 8516d0add67SJakub Kruzik . nmat - number of matrices in the composite matrix 8526a7ede75SJakub Kruzik 8538b5c3584SJakub Kruzik Level: advanced 8546a7ede75SJakub Kruzik 8551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeGetMat()`, `MATCOMPOSITE` 8566a7ede75SJakub Kruzik @*/ 857d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeGetNumberMat(Mat mat, PetscInt *nmat) 858d71ae5a4SJacob Faibussowitsch { 8596a7ede75SJakub Kruzik PetscFunctionBegin; 860d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8614f572ea9SToby Isaac PetscAssertPointer(nmat, 2); 862cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeGetNumberMat_C", (Mat, PetscInt *), (mat, nmat)); 8633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 864d7f81bf2SJakub Kruzik } 865d7f81bf2SJakub Kruzik 866d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCompositeGetMat_Composite(Mat mat, PetscInt i, Mat *Ai) 867d71ae5a4SJacob Faibussowitsch { 868d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite *)mat->data; 869d7f81bf2SJakub Kruzik Mat_CompositeLink ilink; 870d7f81bf2SJakub Kruzik PetscInt k; 871d7f81bf2SJakub Kruzik 872d7f81bf2SJakub Kruzik PetscFunctionBegin; 87308401ef6SPierre Jolivet PetscCheck(i < shell->nmat, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "index out of range: %" PetscInt_FMT " >= %" PetscInt_FMT, i, shell->nmat); 874d7f81bf2SJakub Kruzik ilink = shell->head; 875ad540459SPierre Jolivet for (k = 0; k < i; k++) ilink = ilink->next; 876d7f81bf2SJakub Kruzik *Ai = ilink->mat; 8773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8786a7ede75SJakub Kruzik } 8796a7ede75SJakub Kruzik 8808b5c3584SJakub Kruzik /*@ 8818bd739bdSJakub Kruzik MatCompositeGetMat - Returns the ith matrix from the composite matrix. 8828b5c3584SJakub Kruzik 883c3339decSBarry Smith Logically Collective 8848b5c3584SJakub Kruzik 885d8d19677SJose E. Roman Input Parameters: 886d7f81bf2SJakub Kruzik + mat - the composite matrix 8878b5c3584SJakub Kruzik - i - the number of requested matrix 8888b5c3584SJakub Kruzik 8898b5c3584SJakub Kruzik Output Parameter: 8908b5c3584SJakub Kruzik . Ai - ith matrix in composite 8918b5c3584SJakub Kruzik 8928b5c3584SJakub Kruzik Level: advanced 8938b5c3584SJakub Kruzik 8941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeGetNumberMat()`, `MatCompositeAddMat()`, `MATCOMPOSITE` 8958b5c3584SJakub Kruzik @*/ 896d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeGetMat(Mat mat, PetscInt i, Mat *Ai) 897d71ae5a4SJacob Faibussowitsch { 8988b5c3584SJakub Kruzik PetscFunctionBegin; 899d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 900d7f81bf2SJakub Kruzik PetscValidLogicalCollectiveInt(mat, i, 2); 9014f572ea9SToby Isaac PetscAssertPointer(Ai, 3); 902cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeGetMat_C", (Mat, PetscInt, Mat *), (mat, i, Ai)); 9033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9048b5c3584SJakub Kruzik } 9058b5c3584SJakub Kruzik 90666976f2fSJacob Faibussowitsch static PetscErrorCode MatCompositeSetScalings_Composite(Mat mat, const PetscScalar *scalings) 907d71ae5a4SJacob Faibussowitsch { 90803049c21SJunchao Zhang Mat_Composite *shell = (Mat_Composite *)mat->data; 90903049c21SJunchao Zhang PetscInt nmat; 91003049c21SJunchao Zhang 91103049c21SJunchao Zhang PetscFunctionBegin; 9129566063dSJacob Faibussowitsch PetscCall(MatCompositeGetNumberMat(mat, &nmat)); 9139566063dSJacob Faibussowitsch if (!shell->scalings) PetscCall(PetscMalloc1(nmat, &shell->scalings)); 9149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(shell->scalings, scalings, nmat)); 9153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91603049c21SJunchao Zhang } 91703049c21SJunchao Zhang 91803049c21SJunchao Zhang /*@ 91903049c21SJunchao Zhang MatCompositeSetScalings - Sets separate scaling factors for component matrices. 92003049c21SJunchao Zhang 921c3339decSBarry Smith Logically Collective 92203049c21SJunchao Zhang 923d8d19677SJose E. Roman Input Parameters: 92403049c21SJunchao Zhang + mat - the composite matrix 92503049c21SJunchao Zhang - scalings - array of scaling factors with scalings[i] being factor of i-th matrix, for i in [0, nmat) 92603049c21SJunchao Zhang 92703049c21SJunchao Zhang Level: advanced 92803049c21SJunchao Zhang 9291cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatDiagonalScale()`, `MATCOMPOSITE` 93003049c21SJunchao Zhang @*/ 931d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCompositeSetScalings(Mat mat, const PetscScalar *scalings) 932d71ae5a4SJacob Faibussowitsch { 93303049c21SJunchao Zhang PetscFunctionBegin; 93403049c21SJunchao Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9354f572ea9SToby Isaac PetscAssertPointer(scalings, 2); 93603049c21SJunchao Zhang PetscValidLogicalCollectiveScalar(mat, *scalings, 2); 937cac4c232SBarry Smith PetscUseMethod(mat, "MatCompositeSetScalings_C", (Mat, const PetscScalar *), (mat, scalings)); 9383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93903049c21SJunchao Zhang } 94003049c21SJunchao Zhang 941f4259b30SLisandro Dalcin static struct _MatOps MatOps_Values = {NULL, 942f4259b30SLisandro Dalcin NULL, 943f4259b30SLisandro Dalcin NULL, 94441cd0125SJakub Kruzik MatMult_Composite, 9457bf3a71bSJakub Kruzik MatMultAdd_Composite, 94641cd0125SJakub Kruzik /* 5*/ MatMultTranspose_Composite, 9477bf3a71bSJakub Kruzik MatMultTransposeAdd_Composite, 948f4259b30SLisandro Dalcin NULL, 949f4259b30SLisandro Dalcin NULL, 950f4259b30SLisandro Dalcin NULL, 951f4259b30SLisandro Dalcin /* 10*/ NULL, 952f4259b30SLisandro Dalcin NULL, 953f4259b30SLisandro Dalcin NULL, 954f4259b30SLisandro Dalcin NULL, 955f4259b30SLisandro Dalcin NULL, 956f4259b30SLisandro Dalcin /* 15*/ NULL, 957f4259b30SLisandro Dalcin NULL, 95841cd0125SJakub Kruzik MatGetDiagonal_Composite, 95941cd0125SJakub Kruzik MatDiagonalScale_Composite, 960f4259b30SLisandro Dalcin NULL, 961f4259b30SLisandro Dalcin /* 20*/ NULL, 96241cd0125SJakub Kruzik MatAssemblyEnd_Composite, 963f4259b30SLisandro Dalcin NULL, 964f4259b30SLisandro Dalcin NULL, 965f4259b30SLisandro Dalcin /* 24*/ NULL, 966f4259b30SLisandro Dalcin NULL, 967f4259b30SLisandro Dalcin NULL, 968f4259b30SLisandro Dalcin NULL, 969f4259b30SLisandro Dalcin NULL, 970f4259b30SLisandro Dalcin /* 29*/ NULL, 971f4259b30SLisandro Dalcin NULL, 972f4259b30SLisandro Dalcin NULL, 973f4259b30SLisandro Dalcin NULL, 974f4259b30SLisandro Dalcin NULL, 975f4259b30SLisandro Dalcin /* 34*/ NULL, 976f4259b30SLisandro Dalcin NULL, 977f4259b30SLisandro Dalcin NULL, 978f4259b30SLisandro Dalcin NULL, 979f4259b30SLisandro Dalcin NULL, 980f4259b30SLisandro Dalcin /* 39*/ NULL, 981f4259b30SLisandro Dalcin NULL, 982f4259b30SLisandro Dalcin NULL, 983f4259b30SLisandro Dalcin NULL, 984f4259b30SLisandro Dalcin NULL, 985f4259b30SLisandro Dalcin /* 44*/ NULL, 98641cd0125SJakub Kruzik MatScale_Composite, 98741cd0125SJakub Kruzik MatShift_Basic, 988f4259b30SLisandro Dalcin NULL, 989f4259b30SLisandro Dalcin NULL, 990f4259b30SLisandro Dalcin /* 49*/ NULL, 991f4259b30SLisandro Dalcin NULL, 992f4259b30SLisandro Dalcin NULL, 993f4259b30SLisandro Dalcin NULL, 994f4259b30SLisandro Dalcin NULL, 995f4259b30SLisandro Dalcin /* 54*/ NULL, 996f4259b30SLisandro Dalcin NULL, 997f4259b30SLisandro Dalcin NULL, 998f4259b30SLisandro Dalcin NULL, 999f4259b30SLisandro Dalcin NULL, 1000f4259b30SLisandro Dalcin /* 59*/ NULL, 100141cd0125SJakub Kruzik MatDestroy_Composite, 1002f4259b30SLisandro Dalcin NULL, 1003f4259b30SLisandro Dalcin NULL, 1004f4259b30SLisandro Dalcin NULL, 1005f4259b30SLisandro Dalcin /* 64*/ NULL, 1006f4259b30SLisandro Dalcin NULL, 1007f4259b30SLisandro Dalcin NULL, 1008f4259b30SLisandro Dalcin NULL, 1009f4259b30SLisandro Dalcin NULL, 1010f4259b30SLisandro Dalcin /* 69*/ NULL, 1011f4259b30SLisandro Dalcin NULL, 1012f4259b30SLisandro Dalcin NULL, 1013f4259b30SLisandro Dalcin NULL, 1014f4259b30SLisandro Dalcin NULL, 1015f4259b30SLisandro Dalcin /* 74*/ NULL, 1016f4259b30SLisandro Dalcin NULL, 10174b2558d6SJakub Kruzik MatSetFromOptions_Composite, 1018f4259b30SLisandro Dalcin NULL, 1019f4259b30SLisandro Dalcin NULL, 1020f4259b30SLisandro Dalcin /* 79*/ NULL, 1021f4259b30SLisandro Dalcin NULL, 1022f4259b30SLisandro Dalcin NULL, 1023f4259b30SLisandro Dalcin NULL, 1024f4259b30SLisandro Dalcin NULL, 1025f4259b30SLisandro Dalcin /* 84*/ NULL, 1026f4259b30SLisandro Dalcin NULL, 1027f4259b30SLisandro Dalcin NULL, 1028f4259b30SLisandro Dalcin NULL, 1029f4259b30SLisandro Dalcin NULL, 1030f4259b30SLisandro Dalcin /* 89*/ NULL, 1031f4259b30SLisandro Dalcin NULL, 1032f4259b30SLisandro Dalcin NULL, 1033f4259b30SLisandro Dalcin NULL, 1034f4259b30SLisandro Dalcin NULL, 1035f4259b30SLisandro Dalcin /* 94*/ NULL, 1036f4259b30SLisandro Dalcin NULL, 1037f4259b30SLisandro Dalcin NULL, 1038f4259b30SLisandro Dalcin NULL, 1039f4259b30SLisandro Dalcin NULL, 1040f4259b30SLisandro Dalcin /*99*/ NULL, 1041f4259b30SLisandro Dalcin NULL, 1042f4259b30SLisandro Dalcin NULL, 1043f4259b30SLisandro Dalcin NULL, 1044f4259b30SLisandro Dalcin NULL, 1045f4259b30SLisandro Dalcin /*104*/ NULL, 1046f4259b30SLisandro Dalcin NULL, 1047f4259b30SLisandro Dalcin NULL, 1048f4259b30SLisandro Dalcin NULL, 1049f4259b30SLisandro Dalcin NULL, 1050f4259b30SLisandro Dalcin /*109*/ NULL, 1051f4259b30SLisandro Dalcin NULL, 1052f4259b30SLisandro Dalcin NULL, 1053f4259b30SLisandro Dalcin NULL, 1054f4259b30SLisandro Dalcin NULL, 1055f4259b30SLisandro Dalcin /*114*/ NULL, 1056f4259b30SLisandro Dalcin NULL, 1057f4259b30SLisandro Dalcin NULL, 1058f4259b30SLisandro Dalcin NULL, 1059f4259b30SLisandro Dalcin NULL, 1060f4259b30SLisandro Dalcin /*119*/ NULL, 1061f4259b30SLisandro Dalcin NULL, 1062f4259b30SLisandro Dalcin NULL, 1063f4259b30SLisandro Dalcin NULL, 1064f4259b30SLisandro Dalcin NULL, 1065f4259b30SLisandro Dalcin /*124*/ NULL, 1066f4259b30SLisandro Dalcin NULL, 1067f4259b30SLisandro Dalcin NULL, 1068f4259b30SLisandro Dalcin NULL, 1069f4259b30SLisandro Dalcin NULL, 1070f4259b30SLisandro Dalcin /*129*/ NULL, 1071f4259b30SLisandro Dalcin NULL, 1072f4259b30SLisandro Dalcin NULL, 1073f4259b30SLisandro Dalcin NULL, 1074f4259b30SLisandro Dalcin NULL, 1075f4259b30SLisandro Dalcin /*134*/ NULL, 1076f4259b30SLisandro Dalcin NULL, 1077f4259b30SLisandro Dalcin NULL, 1078f4259b30SLisandro Dalcin NULL, 1079f4259b30SLisandro Dalcin NULL, 1080f4259b30SLisandro Dalcin /*139*/ NULL, 1081f4259b30SLisandro Dalcin NULL, 1082d70f29a3SPierre Jolivet NULL, 1083d70f29a3SPierre Jolivet NULL, 1084d70f29a3SPierre Jolivet NULL, 1085d70f29a3SPierre Jolivet /*144*/ NULL, 1086d70f29a3SPierre Jolivet NULL, 1087d70f29a3SPierre Jolivet NULL, 108899a7f59eSMark Adams NULL, 108999a7f59eSMark Adams NULL, 10907fb60732SBarry Smith NULL, 1091dec0b466SHong Zhang /*150*/ NULL, 1092dec0b466SHong Zhang NULL}; 109341cd0125SJakub Kruzik 109441cd0125SJakub Kruzik /*MC 109541cd0125SJakub Kruzik MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices. 109641cd0125SJakub Kruzik The matrices need to have a correct size and parallel layout for the sum or product to be valid. 109741cd0125SJakub Kruzik 10982ef1f0ffSBarry Smith Level: advanced 10992ef1f0ffSBarry Smith 110011a5261eSBarry Smith Note: 110111a5261eSBarry Smith To use the product of the matrices call `MatCompositeSetType`(mat,`MAT_COMPOSITE_MULTIPLICATIVE`); 110241cd0125SJakub Kruzik 11031cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateComposite()`, `MatCompositeSetScalings()`, `MatCompositeAddMat()`, `MatSetType()`, `MatCompositeSetType()`, `MatCompositeGetType()`, 110411a5261eSBarry Smith `MatCompositeSetMatStructure()`, `MatCompositeGetMatStructure()`, `MatCompositeMerge()`, `MatCompositeSetMergeType()`, `MatCompositeGetNumberMat()`, `MatCompositeGetMat()` 110541cd0125SJakub Kruzik M*/ 110641cd0125SJakub Kruzik 1107d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) 1108d71ae5a4SJacob Faibussowitsch { 110941cd0125SJakub Kruzik Mat_Composite *b; 111041cd0125SJakub Kruzik 111141cd0125SJakub Kruzik PetscFunctionBegin; 11124dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 111341cd0125SJakub Kruzik A->data = (void *)b; 1114aea10558SJacob Faibussowitsch A->ops[0] = MatOps_Values; 111541cd0125SJakub Kruzik 11169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 11179566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 111841cd0125SJakub Kruzik 111941cd0125SJakub Kruzik A->assembled = PETSC_TRUE; 112041cd0125SJakub Kruzik A->preallocated = PETSC_TRUE; 112141cd0125SJakub Kruzik b->type = MAT_COMPOSITE_ADDITIVE; 112241cd0125SJakub Kruzik b->scale = 1.0; 112341cd0125SJakub Kruzik b->nmat = 0; 11244b2558d6SJakub Kruzik b->merge = PETSC_FALSE; 11258c8613bfSJakub Kruzik b->mergetype = MAT_COMPOSITE_MERGE_RIGHT; 11263b35acafSJakub Kruzik b->structure = DIFFERENT_NONZERO_PATTERN; 112703049c21SJunchao Zhang b->merge_mvctx = PETSC_TRUE; 112803049c21SJunchao Zhang 11299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeAddMat_C", MatCompositeAddMat_Composite)); 11309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetType_C", MatCompositeSetType_Composite)); 11319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetType_C", MatCompositeGetType_Composite)); 11329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetMergeType_C", MatCompositeSetMergeType_Composite)); 11339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetMatStructure_C", MatCompositeSetMatStructure_Composite)); 11349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetMatStructure_C", MatCompositeGetMatStructure_Composite)); 11359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeMerge_C", MatCompositeMerge_Composite)); 11369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetNumberMat_C", MatCompositeGetNumberMat_Composite)); 11379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetMat_C", MatCompositeGetMat_Composite)); 11389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetScalings_C", MatCompositeSetScalings_Composite)); 113941cd0125SJakub Kruzik 11409566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATCOMPOSITE)); 11413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 114241cd0125SJakub Kruzik } 1143