xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1793850ffSBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
3793850ffSBarry Smith 
4f4259b30SLisandro Dalcin const char *const MatCompositeMergeTypes[] = {"left", "right", "MatCompositeMergeType", "MAT_COMPOSITE_", NULL};
58c8613bfSJakub Kruzik 
6793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink;
7793850ffSBarry Smith struct _Mat_CompositeLink {
8793850ffSBarry Smith   Mat               mat;
96d7c1e57SBarry Smith   Vec               work;
106d7c1e57SBarry Smith   Mat_CompositeLink next, prev;
11793850ffSBarry Smith };
12793850ffSBarry Smith 
13793850ffSBarry Smith typedef struct {
146d7c1e57SBarry Smith   MatCompositeType      type;
156d7c1e57SBarry Smith   Mat_CompositeLink     head, tail;
16793850ffSBarry Smith   Vec                   work;
17e4fc5df0SBarry Smith   PetscScalar           scale;                                      /* scale factor supplied with MatScale() */
18e4fc5df0SBarry Smith   Vec                   left, right;                                /* left and right diagonal scaling provided with MatDiagonalScale() */
1903049c21SJunchao Zhang   Vec                   leftwork, rightwork, leftwork2, rightwork2; /* Two pairs of working vectors */
206a7ede75SJakub Kruzik   PetscInt              nmat;
214b2558d6SJakub Kruzik   PetscBool             merge;
228c8613bfSJakub Kruzik   MatCompositeMergeType mergetype;
233b35acafSJakub Kruzik   MatStructure          structure;
2403049c21SJunchao Zhang 
2503049c21SJunchao Zhang   PetscScalar *scalings;
2603049c21SJunchao Zhang   PetscBool    merge_mvctx; /* Whether need to merge mvctx of component matrices */
2703049c21SJunchao Zhang   Vec         *lvecs;       /* [nmat] Basically, they are Mvctx->lvec of each component matrix */
2803049c21SJunchao Zhang   PetscScalar *larray;      /* [len] Data arrays of lvecs[] are stored consecutively in larray */
2903049c21SJunchao Zhang   PetscInt     len;         /* Length of larray[] */
3003049c21SJunchao Zhang   Vec          gvec;        /* Union of lvecs[] without duplicated entries */
3103049c21SJunchao Zhang   PetscInt    *location;    /* A map that maps entries in garray[] to larray[] */
3203049c21SJunchao Zhang   VecScatter   Mvctx;
33793850ffSBarry Smith } Mat_Composite;
34793850ffSBarry Smith 
359371c9d4SSatish Balay PetscErrorCode MatDestroy_Composite(Mat mat) {
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));
43*48a46eb9SPierre 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));
76793850ffSBarry Smith   PetscFunctionReturn(0);
77793850ffSBarry Smith }
78793850ffSBarry Smith 
799371c9d4SSatish Balay PetscErrorCode MatMult_Composite_Multiplicative(Mat A, Vec x, Vec y) {
806d7c1e57SBarry Smith   Mat_Composite    *shell = (Mat_Composite *)A->data;
816d7c1e57SBarry Smith   Mat_CompositeLink next  = shell->head;
826d7c1e57SBarry Smith   Vec               in, out;
8303049c21SJunchao Zhang   PetscScalar       scale;
8403049c21SJunchao Zhang   PetscInt          i;
856d7c1e57SBarry Smith 
866d7c1e57SBarry Smith   PetscFunctionBegin;
8728b400f6SJacob Faibussowitsch   PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
886d7c1e57SBarry Smith   in = x;
89e4fc5df0SBarry Smith   if (shell->right) {
90*48a46eb9SPierre Jolivet     if (!shell->rightwork) PetscCall(VecDuplicate(shell->right, &shell->rightwork));
919566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(shell->rightwork, shell->right, in));
92e4fc5df0SBarry Smith     in = shell->rightwork;
93e4fc5df0SBarry Smith   }
946d7c1e57SBarry Smith   while (next->next) {
956d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
969566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(next->mat, NULL, &next->work));
976d7c1e57SBarry Smith     }
986d7c1e57SBarry Smith     out = next->work;
999566063dSJacob Faibussowitsch     PetscCall(MatMult(next->mat, in, out));
1006d7c1e57SBarry Smith     in   = out;
1016d7c1e57SBarry Smith     next = next->next;
1026d7c1e57SBarry Smith   }
1039566063dSJacob Faibussowitsch   PetscCall(MatMult(next->mat, in, y));
1041baa6e33SBarry Smith   if (shell->left) PetscCall(VecPointwiseMult(y, shell->left, y));
10503049c21SJunchao Zhang   scale = shell->scale;
1069371c9d4SSatish Balay   if (shell->scalings) {
1079371c9d4SSatish Balay     for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i];
1089371c9d4SSatish Balay   }
1099566063dSJacob Faibussowitsch   PetscCall(VecScale(y, scale));
1106d7c1e57SBarry Smith   PetscFunctionReturn(0);
1116d7c1e57SBarry Smith }
1126d7c1e57SBarry Smith 
1139371c9d4SSatish Balay PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A, Vec x, Vec y) {
1146d7c1e57SBarry Smith   Mat_Composite    *shell = (Mat_Composite *)A->data;
1156d7c1e57SBarry Smith   Mat_CompositeLink tail  = shell->tail;
1166d7c1e57SBarry Smith   Vec               in, out;
11703049c21SJunchao Zhang   PetscScalar       scale;
11803049c21SJunchao Zhang   PetscInt          i;
1196d7c1e57SBarry Smith 
1206d7c1e57SBarry Smith   PetscFunctionBegin;
12128b400f6SJacob Faibussowitsch   PetscCheck(tail, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
1226d7c1e57SBarry Smith   in = x;
123e4fc5df0SBarry Smith   if (shell->left) {
124*48a46eb9SPierre Jolivet     if (!shell->leftwork) PetscCall(VecDuplicate(shell->left, &shell->leftwork));
1259566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(shell->leftwork, shell->left, in));
126e4fc5df0SBarry Smith     in = shell->leftwork;
127e4fc5df0SBarry Smith   }
1286d7c1e57SBarry Smith   while (tail->prev) {
1296d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
1309566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(tail->mat, NULL, &tail->prev->work));
1316d7c1e57SBarry Smith     }
1326d7c1e57SBarry Smith     out = tail->prev->work;
1339566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tail->mat, in, out));
1346d7c1e57SBarry Smith     in   = out;
1356d7c1e57SBarry Smith     tail = tail->prev;
1366d7c1e57SBarry Smith   }
1379566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(tail->mat, in, y));
1381baa6e33SBarry Smith   if (shell->right) PetscCall(VecPointwiseMult(y, shell->right, y));
13903049c21SJunchao Zhang 
14003049c21SJunchao Zhang   scale = shell->scale;
1419371c9d4SSatish Balay   if (shell->scalings) {
1429371c9d4SSatish Balay     for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i];
1439371c9d4SSatish Balay   }
1449566063dSJacob Faibussowitsch   PetscCall(VecScale(y, scale));
1456d7c1e57SBarry Smith   PetscFunctionReturn(0);
1466d7c1e57SBarry Smith }
1476d7c1e57SBarry Smith 
1489371c9d4SSatish Balay PetscErrorCode MatMult_Composite(Mat mat, Vec x, Vec y) {
14903049c21SJunchao Zhang   Mat_Composite     *shell = (Mat_Composite *)mat->data;
15003049c21SJunchao Zhang   Mat_CompositeLink  cur   = shell->head;
15103049c21SJunchao Zhang   Vec                in, y2, xin;
15203049c21SJunchao Zhang   Mat                A, B;
15303049c21SJunchao Zhang   PetscInt           i, j, k, n, nuniq, lo, hi, mid, *gindices, *buf, *tmp, tot;
15403049c21SJunchao Zhang   const PetscScalar *vals;
15503049c21SJunchao Zhang   const PetscInt    *garray;
15603049c21SJunchao Zhang   IS                 ix, iy;
15703049c21SJunchao Zhang   PetscBool          match;
158793850ffSBarry Smith 
159793850ffSBarry Smith   PetscFunctionBegin;
16028b400f6SJacob Faibussowitsch   PetscCheck(cur, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
161e4fc5df0SBarry Smith   in = x;
162e4fc5df0SBarry Smith   if (shell->right) {
163*48a46eb9SPierre Jolivet     if (!shell->rightwork) PetscCall(VecDuplicate(shell->right, &shell->rightwork));
1649566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(shell->rightwork, shell->right, in));
165e4fc5df0SBarry Smith     in = shell->rightwork;
166e4fc5df0SBarry Smith   }
16703049c21SJunchao Zhang 
16803049c21SJunchao Zhang   /* Try to merge Mvctx when instructed but not yet done. We did not do it in MatAssemblyEnd() since at that time
16903049c21SJunchao Zhang      we did not know whether mat is ADDITIVE or MULTIPLICATIVE. Only now we are assured mat is ADDITIVE and
17003049c21SJunchao Zhang      it is legal to merge Mvctx, because all component matrices have the same size.
17103049c21SJunchao Zhang    */
17203049c21SJunchao Zhang   if (shell->merge_mvctx && !shell->Mvctx) {
17303049c21SJunchao Zhang     /* Currently only implemented for MATMPIAIJ */
17403049c21SJunchao Zhang     for (cur = shell->head; cur; cur = cur->next) {
1759566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)cur->mat, MATMPIAIJ, &match));
17603049c21SJunchao Zhang       if (!match) {
17703049c21SJunchao Zhang         shell->merge_mvctx = PETSC_FALSE;
17803049c21SJunchao Zhang         goto skip_merge_mvctx;
179e4fc5df0SBarry Smith       }
180e4fc5df0SBarry Smith     }
18103049c21SJunchao Zhang 
18203049c21SJunchao Zhang     /* Go through matrices first time to count total number of nonzero off-diag columns (may have dups) */
18303049c21SJunchao Zhang     tot = 0;
18403049c21SJunchao Zhang     for (cur = shell->head; cur; cur = cur->next) {
1859566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, NULL));
1869566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(B, NULL, &n));
18703049c21SJunchao Zhang       tot += n;
18803049c21SJunchao Zhang     }
1899566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(tot, &shell->location, tot, &shell->larray, shell->nmat, &shell->lvecs));
19003049c21SJunchao Zhang     shell->len = tot;
19103049c21SJunchao Zhang 
19203049c21SJunchao Zhang     /* Go through matrices second time to sort off-diag columns and remove dups */
1939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(tot, &gindices)); /* No Malloc2() since we will give one to petsc and free the other */
1949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(tot, &buf));
19503049c21SJunchao Zhang     nuniq = 0; /* Number of unique nonzero columns */
19603049c21SJunchao Zhang     for (cur = shell->head; cur; cur = cur->next) {
1979566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, &garray));
1989566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(B, NULL, &n));
19903049c21SJunchao Zhang       /* Merge pre-sorted garray[0,n) and gindices[0,nuniq) to buf[] */
20003049c21SJunchao Zhang       i = j = k = 0;
20103049c21SJunchao Zhang       while (i < n && j < nuniq) {
20203049c21SJunchao Zhang         if (garray[i] < gindices[j]) buf[k++] = garray[i++];
20303049c21SJunchao Zhang         else if (garray[i] > gindices[j]) buf[k++] = gindices[j++];
2049371c9d4SSatish Balay         else {
2059371c9d4SSatish Balay           buf[k++] = garray[i++];
2069371c9d4SSatish Balay           j++;
2079371c9d4SSatish Balay         }
20803049c21SJunchao Zhang       }
20903049c21SJunchao Zhang       /* Copy leftover in garray[] or gindices[] */
21003049c21SJunchao Zhang       if (i < n) {
2119566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(buf + k, garray + i, n - i));
21203049c21SJunchao Zhang         nuniq = k + n - i;
21303049c21SJunchao Zhang       } else if (j < nuniq) {
2149566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(buf + k, gindices + j, nuniq - j));
21503049c21SJunchao Zhang         nuniq = k + nuniq - j;
21603049c21SJunchao Zhang       } else nuniq = k;
21703049c21SJunchao Zhang       /* Swap gindices and buf to merge garray of the next matrix */
21803049c21SJunchao Zhang       tmp      = gindices;
21903049c21SJunchao Zhang       gindices = buf;
22003049c21SJunchao Zhang       buf      = tmp;
22103049c21SJunchao Zhang     }
2229566063dSJacob Faibussowitsch     PetscCall(PetscFree(buf));
22303049c21SJunchao Zhang 
22403049c21SJunchao Zhang     /* Go through matrices third time to build a map from gindices[] to garray[] */
22503049c21SJunchao Zhang     tot = 0;
22603049c21SJunchao Zhang     for (cur = shell->head, j = 0; cur; cur = cur->next, j++) { /* j-th matrix */
2279566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, NULL, &B, &garray));
2289566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(B, NULL, &n));
2299566063dSJacob Faibussowitsch       PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, n, NULL, &shell->lvecs[j]));
23003049c21SJunchao Zhang       /* This is an optimized PetscFindInt(garray[i],nuniq,gindices,&shell->location[tot+i]), using the fact that garray[] is also sorted */
23103049c21SJunchao Zhang       lo = 0;
23203049c21SJunchao Zhang       for (i = 0; i < n; i++) {
23303049c21SJunchao Zhang         hi = nuniq;
23403049c21SJunchao Zhang         while (hi - lo > 1) {
23503049c21SJunchao Zhang           mid = lo + (hi - lo) / 2;
23603049c21SJunchao Zhang           if (garray[i] < gindices[mid]) hi = mid;
23703049c21SJunchao Zhang           else lo = mid;
23803049c21SJunchao Zhang         }
23903049c21SJunchao Zhang         shell->location[tot + i] = lo; /* gindices[lo] = garray[i] */
24003049c21SJunchao Zhang         lo++;                          /* Since garray[i+1] > garray[i], we can safely advance lo */
24103049c21SJunchao Zhang       }
24203049c21SJunchao Zhang       tot += n;
24303049c21SJunchao Zhang     }
24403049c21SJunchao Zhang 
24503049c21SJunchao Zhang     /* Build merged Mvctx */
2469566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nuniq, gindices, PETSC_OWN_POINTER, &ix));
2479566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, nuniq, 0, 1, &iy));
2489566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)mat), 1, mat->cmap->n, mat->cmap->N, NULL, &xin));
2499566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, nuniq, &shell->gvec));
2509566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(xin, ix, shell->gvec, iy, &shell->Mvctx));
2519566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xin));
2529566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ix));
2539566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&iy));
25403049c21SJunchao Zhang   }
25503049c21SJunchao Zhang 
25603049c21SJunchao Zhang skip_merge_mvctx:
2579566063dSJacob Faibussowitsch   PetscCall(VecSet(y, 0));
2589566063dSJacob Faibussowitsch   if (!shell->leftwork2) PetscCall(VecDuplicate(y, &shell->leftwork2));
25903049c21SJunchao Zhang   y2 = shell->leftwork2;
26003049c21SJunchao Zhang 
26103049c21SJunchao Zhang   if (shell->Mvctx) { /* Have a merged Mvctx */
26203049c21SJunchao 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
26303049c21SJunchao Zhang        in y = s(Ax1 + Bx2) or y = sAx1 + sBx2. The former incurs less FLOPS than the latter, but the latter provides an oppertunity to
26403049c21SJunchao Zhang        overlap communication/computation since we can do sAx1 while communicating x2. Here, we use the former approach.
26503049c21SJunchao Zhang      */
2669566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(shell->Mvctx, in, shell->gvec, INSERT_VALUES, SCATTER_FORWARD));
2679566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(shell->Mvctx, in, shell->gvec, INSERT_VALUES, SCATTER_FORWARD));
26803049c21SJunchao Zhang 
2699566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(shell->gvec, &vals));
27003049c21SJunchao Zhang     for (i = 0; i < shell->len; i++) shell->larray[i] = vals[shell->location[i]];
2719566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(shell->gvec, &vals));
27203049c21SJunchao Zhang 
27303049c21SJunchao Zhang     for (cur = shell->head, tot = i = 0; cur; cur = cur->next, i++) { /* i-th matrix */
2749566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(cur->mat, &A, &B, NULL));
275dbbe0bcdSBarry Smith       PetscUseTypeMethod(A, mult, in, y2);
2769566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(B, NULL, &n));
2779566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(shell->lvecs[i], &shell->larray[tot]));
2789566063dSJacob Faibussowitsch       PetscCall((*B->ops->multadd)(B, shell->lvecs[i], y2, y2));
2799566063dSJacob Faibussowitsch       PetscCall(VecResetArray(shell->lvecs[i]));
2809566063dSJacob Faibussowitsch       PetscCall(VecAXPY(y, (shell->scalings ? shell->scalings[i] : 1.0), y2));
28103049c21SJunchao Zhang       tot += n;
28203049c21SJunchao Zhang     }
28303049c21SJunchao Zhang   } else {
28403049c21SJunchao Zhang     if (shell->scalings) {
28503049c21SJunchao Zhang       for (cur = shell->head, i = 0; cur; cur = cur->next, i++) {
2869566063dSJacob Faibussowitsch         PetscCall(MatMult(cur->mat, in, y2));
2879566063dSJacob Faibussowitsch         PetscCall(VecAXPY(y, shell->scalings[i], y2));
28803049c21SJunchao Zhang       }
28903049c21SJunchao Zhang     } else {
2909566063dSJacob Faibussowitsch       for (cur = shell->head; cur; cur = cur->next) PetscCall(MatMultAdd(cur->mat, in, y, y));
29103049c21SJunchao Zhang     }
29203049c21SJunchao Zhang   }
29303049c21SJunchao Zhang 
2949566063dSJacob Faibussowitsch   if (shell->left) PetscCall(VecPointwiseMult(y, shell->left, y));
2959566063dSJacob Faibussowitsch   PetscCall(VecScale(y, shell->scale));
296793850ffSBarry Smith   PetscFunctionReturn(0);
297793850ffSBarry Smith }
298793850ffSBarry Smith 
2999371c9d4SSatish Balay PetscErrorCode MatMultTranspose_Composite(Mat A, Vec x, Vec y) {
300793850ffSBarry Smith   Mat_Composite    *shell = (Mat_Composite *)A->data;
301793850ffSBarry Smith   Mat_CompositeLink next  = shell->head;
30203049c21SJunchao Zhang   Vec               in, y2 = NULL;
30303049c21SJunchao Zhang   PetscInt          i;
304793850ffSBarry Smith 
305793850ffSBarry Smith   PetscFunctionBegin;
30628b400f6SJacob Faibussowitsch   PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
307e4fc5df0SBarry Smith   in = x;
308e4fc5df0SBarry Smith   if (shell->left) {
309*48a46eb9SPierre Jolivet     if (!shell->leftwork) PetscCall(VecDuplicate(shell->left, &shell->leftwork));
3109566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(shell->leftwork, shell->left, in));
311e4fc5df0SBarry Smith     in = shell->leftwork;
312e4fc5df0SBarry Smith   }
31303049c21SJunchao Zhang 
3149566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(next->mat, in, y));
31503049c21SJunchao Zhang   if (shell->scalings) {
3169566063dSJacob Faibussowitsch     PetscCall(VecScale(y, shell->scalings[0]));
3179566063dSJacob Faibussowitsch     if (!shell->rightwork2) PetscCall(VecDuplicate(y, &shell->rightwork2));
31803049c21SJunchao Zhang     y2 = shell->rightwork2;
31903049c21SJunchao Zhang   }
32003049c21SJunchao Zhang   i = 1;
321e4fc5df0SBarry Smith   while ((next = next->next)) {
3229566063dSJacob Faibussowitsch     if (!shell->scalings) PetscCall(MatMultTransposeAdd(next->mat, in, y, y));
32303049c21SJunchao Zhang     else {
3249566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(next->mat, in, y2));
3259566063dSJacob Faibussowitsch       PetscCall(VecAXPY(y, shell->scalings[i++], y2));
32603049c21SJunchao Zhang     }
327e4fc5df0SBarry Smith   }
3281baa6e33SBarry Smith   if (shell->right) PetscCall(VecPointwiseMult(y, shell->right, y));
3299566063dSJacob Faibussowitsch   PetscCall(VecScale(y, shell->scale));
330793850ffSBarry Smith   PetscFunctionReturn(0);
331793850ffSBarry Smith }
332793850ffSBarry Smith 
3339371c9d4SSatish Balay PetscErrorCode MatMultAdd_Composite(Mat A, Vec x, Vec y, Vec z) {
3347bf3a71bSJakub Kruzik   Mat_Composite *shell = (Mat_Composite *)A->data;
3357bf3a71bSJakub Kruzik 
3367bf3a71bSJakub Kruzik   PetscFunctionBegin;
3377bf3a71bSJakub Kruzik   if (y != z) {
3389566063dSJacob Faibussowitsch     PetscCall(MatMult(A, x, z));
3399566063dSJacob Faibussowitsch     PetscCall(VecAXPY(z, 1.0, y));
3407bf3a71bSJakub Kruzik   } else {
341*48a46eb9SPierre Jolivet     if (!shell->leftwork) PetscCall(VecDuplicate(z, &shell->leftwork));
3429566063dSJacob Faibussowitsch     PetscCall(MatMult(A, x, shell->leftwork));
3439566063dSJacob Faibussowitsch     PetscCall(VecCopy(y, z));
3449566063dSJacob Faibussowitsch     PetscCall(VecAXPY(z, 1.0, shell->leftwork));
3457bf3a71bSJakub Kruzik   }
3467bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
3477bf3a71bSJakub Kruzik }
3487bf3a71bSJakub Kruzik 
3499371c9d4SSatish Balay PetscErrorCode MatMultTransposeAdd_Composite(Mat A, Vec x, Vec y, Vec z) {
3507bf3a71bSJakub Kruzik   Mat_Composite *shell = (Mat_Composite *)A->data;
3517bf3a71bSJakub Kruzik 
3527bf3a71bSJakub Kruzik   PetscFunctionBegin;
3537bf3a71bSJakub Kruzik   if (y != z) {
3549566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A, x, z));
3559566063dSJacob Faibussowitsch     PetscCall(VecAXPY(z, 1.0, y));
3567bf3a71bSJakub Kruzik   } else {
357*48a46eb9SPierre Jolivet     if (!shell->rightwork) PetscCall(VecDuplicate(z, &shell->rightwork));
3589566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A, x, shell->rightwork));
3599566063dSJacob Faibussowitsch     PetscCall(VecCopy(y, z));
3609566063dSJacob Faibussowitsch     PetscCall(VecAXPY(z, 1.0, shell->rightwork));
3617bf3a71bSJakub Kruzik   }
3627bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
3637bf3a71bSJakub Kruzik }
3647bf3a71bSJakub Kruzik 
3659371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_Composite(Mat A, Vec v) {
366793850ffSBarry Smith   Mat_Composite    *shell = (Mat_Composite *)A->data;
367793850ffSBarry Smith   Mat_CompositeLink next  = shell->head;
36803049c21SJunchao Zhang   PetscInt          i;
369793850ffSBarry Smith 
370793850ffSBarry Smith   PetscFunctionBegin;
37128b400f6SJacob Faibussowitsch   PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
37208401ef6SPierre Jolivet   PetscCheck(!shell->right && !shell->left, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get diagonal if left or right scaling");
373e4fc5df0SBarry Smith 
3749566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(next->mat, v));
3759566063dSJacob Faibussowitsch   if (shell->scalings) PetscCall(VecScale(v, shell->scalings[0]));
37603049c21SJunchao Zhang 
377*48a46eb9SPierre Jolivet   if (next->next && !shell->work) PetscCall(VecDuplicate(v, &shell->work));
37803049c21SJunchao Zhang   i = 1;
379793850ffSBarry Smith   while ((next = next->next)) {
3809566063dSJacob Faibussowitsch     PetscCall(MatGetDiagonal(next->mat, shell->work));
3819566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v, (shell->scalings ? shell->scalings[i++] : 1.0), shell->work));
382793850ffSBarry Smith   }
3839566063dSJacob Faibussowitsch   PetscCall(VecScale(v, shell->scale));
384793850ffSBarry Smith   PetscFunctionReturn(0);
385793850ffSBarry Smith }
386793850ffSBarry Smith 
3879371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_Composite(Mat Y, MatAssemblyType t) {
3884b2558d6SJakub Kruzik   Mat_Composite *shell = (Mat_Composite *)Y->data;
389b52f573bSBarry Smith 
390793850ffSBarry Smith   PetscFunctionBegin;
3911baa6e33SBarry Smith   if (shell->merge) PetscCall(MatCompositeMerge(Y));
392793850ffSBarry Smith   PetscFunctionReturn(0);
393793850ffSBarry Smith }
394793850ffSBarry Smith 
3959371c9d4SSatish Balay PetscErrorCode MatScale_Composite(Mat inA, PetscScalar alpha) {
396e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite *)inA->data;
397e4fc5df0SBarry Smith 
398e4fc5df0SBarry Smith   PetscFunctionBegin;
399321429dbSBarry Smith   a->scale *= alpha;
400e4fc5df0SBarry Smith   PetscFunctionReturn(0);
401e4fc5df0SBarry Smith }
402e4fc5df0SBarry Smith 
4039371c9d4SSatish Balay PetscErrorCode MatDiagonalScale_Composite(Mat inA, Vec left, Vec right) {
404e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite *)inA->data;
405e4fc5df0SBarry Smith 
406e4fc5df0SBarry Smith   PetscFunctionBegin;
407e4fc5df0SBarry Smith   if (left) {
408321429dbSBarry Smith     if (!a->left) {
4099566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(left, &a->left));
4109566063dSJacob Faibussowitsch       PetscCall(VecCopy(left, a->left));
411321429dbSBarry Smith     } else {
4129566063dSJacob Faibussowitsch       PetscCall(VecPointwiseMult(a->left, left, a->left));
413321429dbSBarry Smith     }
414e4fc5df0SBarry Smith   }
415e4fc5df0SBarry Smith   if (right) {
416321429dbSBarry Smith     if (!a->right) {
4179566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(right, &a->right));
4189566063dSJacob Faibussowitsch       PetscCall(VecCopy(right, a->right));
419321429dbSBarry Smith     } else {
4209566063dSJacob Faibussowitsch       PetscCall(VecPointwiseMult(a->right, right, a->right));
421321429dbSBarry Smith     }
422e4fc5df0SBarry Smith   }
423e4fc5df0SBarry Smith   PetscFunctionReturn(0);
424e4fc5df0SBarry Smith }
425793850ffSBarry Smith 
4269371c9d4SSatish Balay PetscErrorCode MatSetFromOptions_Composite(Mat A, PetscOptionItems *PetscOptionsObject) {
4274b2558d6SJakub Kruzik   Mat_Composite *a = (Mat_Composite *)A->data;
4284b2558d6SJakub Kruzik 
4294b2558d6SJakub Kruzik   PetscFunctionBegin;
430d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "MATCOMPOSITE options");
4319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_composite_merge", "Merge at MatAssemblyEnd", "MatCompositeMerge", a->merge, &a->merge, NULL));
4329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-mat_composite_merge_type", "Set composite merge direction", "MatCompositeSetMergeType", MatCompositeMergeTypes, (PetscEnum)a->mergetype, (PetscEnum *)&a->mergetype, NULL));
4339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_composite_merge_mvctx", "Merge MatMult() vecscat contexts", "MatCreateComposite", a->merge_mvctx, &a->merge_mvctx, NULL));
434d0609cedSBarry Smith   PetscOptionsHeadEnd();
4354b2558d6SJakub Kruzik   PetscFunctionReturn(0);
4364b2558d6SJakub Kruzik }
4374b2558d6SJakub Kruzik 
4382c0821f3SBarry Smith /*@
4398bd739bdSJakub Kruzik    MatCreateComposite - Creates a matrix as the sum or product of one or more matrices
440793850ffSBarry Smith 
441d083f849SBarry Smith   Collective
442793850ffSBarry Smith 
443793850ffSBarry Smith    Input Parameters:
444793850ffSBarry Smith +  comm - MPI communicator
445793850ffSBarry Smith .  nmat - number of matrices to put in
446793850ffSBarry Smith -  mats - the matrices
447793850ffSBarry Smith 
448793850ffSBarry Smith    Output Parameter:
449db36af27SMatthew G. Knepley .  mat - the matrix
450793850ffSBarry Smith 
4514b2558d6SJakub Kruzik    Options Database Keys:
4524b2558d6SJakub Kruzik +  -mat_composite_merge         - merge in MatAssemblyEnd()
45303049c21SJunchao Zhang .  -mat_composite_merge_mvctx   - merge Mvctx of component matrices to optimize communication in MatMult() for ADDITIVE matrices
454b28d0daaSJakub Kruzik -  -mat_composite_merge_type    - set merge direction
4554b2558d6SJakub Kruzik 
456793850ffSBarry Smith    Level: advanced
457793850ffSBarry Smith 
458793850ffSBarry Smith    Notes:
459793850ffSBarry Smith      Alternative construction
460793850ffSBarry Smith $       MatCreate(comm,&mat);
461793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
462793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
463793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
464793850ffSBarry Smith $       ....
465793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
466b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
467b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
468793850ffSBarry Smith 
4696d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
4706d7c1e57SBarry Smith 
471db781477SPatrick Sanan .seealso: `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCompositeGetMat()`, `MatCompositeMerge()`, `MatCompositeSetType()`, `MATCOMPOSITE`
472793850ffSBarry Smith 
473793850ffSBarry Smith @*/
4749371c9d4SSatish Balay PetscErrorCode MatCreateComposite(MPI_Comm comm, PetscInt nmat, const Mat *mats, Mat *mat) {
475793850ffSBarry Smith   PetscInt m, n, M, N, i;
476793850ffSBarry Smith 
477793850ffSBarry Smith   PetscFunctionBegin;
47808401ef6SPierre Jolivet   PetscCheck(nmat >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must pass in at least one matrix");
479064a246eSJacob Faibussowitsch   PetscValidPointer(mat, 4);
480793850ffSBarry Smith 
4819566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mats[0], PETSC_IGNORE, &n));
4829566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mats[nmat - 1], &m, PETSC_IGNORE));
4839566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mats[0], PETSC_IGNORE, &N));
4849566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mats[nmat - 1], &M, PETSC_IGNORE));
4859566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, mat));
4869566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mat, m, n, M, N));
4879566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mat, MATCOMPOSITE));
488*48a46eb9SPierre Jolivet   for (i = 0; i < nmat; i++) PetscCall(MatCompositeAddMat(*mat, mats[i]));
4899566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
4909566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
491793850ffSBarry Smith   PetscFunctionReturn(0);
492793850ffSBarry Smith }
493793850ffSBarry Smith 
4949371c9d4SSatish Balay static PetscErrorCode MatCompositeAddMat_Composite(Mat mat, Mat smat) {
495d7f81bf2SJakub Kruzik   Mat_Composite    *shell = (Mat_Composite *)mat->data;
496d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink, next = shell->head;
497d7f81bf2SJakub Kruzik 
498d7f81bf2SJakub Kruzik   PetscFunctionBegin;
4999566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(mat, &ilink));
500f4259b30SLisandro Dalcin   ilink->next = NULL;
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)smat));
502d7f81bf2SJakub Kruzik   ilink->mat = smat;
503d7f81bf2SJakub Kruzik 
504d7f81bf2SJakub Kruzik   if (!next) shell->head = ilink;
505d7f81bf2SJakub Kruzik   else {
5069371c9d4SSatish Balay     while (next->next) { next = next->next; }
507d7f81bf2SJakub Kruzik     next->next  = ilink;
508d7f81bf2SJakub Kruzik     ilink->prev = next;
509d7f81bf2SJakub Kruzik   }
510d7f81bf2SJakub Kruzik   shell->tail = ilink;
511d7f81bf2SJakub Kruzik   shell->nmat += 1;
51203049c21SJunchao Zhang 
51303049c21SJunchao Zhang   /* Retain the old scalings (if any) and expand it with a 1.0 for the newly added matrix */
51403049c21SJunchao Zhang   if (shell->scalings) {
5159566063dSJacob Faibussowitsch     PetscCall(PetscRealloc(sizeof(PetscScalar) * shell->nmat, &shell->scalings));
51603049c21SJunchao Zhang     shell->scalings[shell->nmat - 1] = 1.0;
51703049c21SJunchao Zhang   }
518d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
519d7f81bf2SJakub Kruzik }
520d7f81bf2SJakub Kruzik 
521793850ffSBarry Smith /*@
5228bd739bdSJakub Kruzik     MatCompositeAddMat - Add another matrix to a composite matrix.
523793850ffSBarry Smith 
524793850ffSBarry Smith    Collective on Mat
525793850ffSBarry Smith 
526793850ffSBarry Smith     Input Parameters:
527793850ffSBarry Smith +   mat - the composite matrix
528793850ffSBarry Smith -   smat - the partial matrix
529793850ffSBarry Smith 
530793850ffSBarry Smith    Level: advanced
531793850ffSBarry Smith 
532db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeGetMat()`, `MATCOMPOSITE`
533793850ffSBarry Smith @*/
5349371c9d4SSatish Balay PetscErrorCode MatCompositeAddMat(Mat mat, Mat smat) {
535793850ffSBarry Smith   PetscFunctionBegin;
5360700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5370700a824SBarry Smith   PetscValidHeaderSpecific(smat, MAT_CLASSID, 2);
538cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeAddMat_C", (Mat, Mat), (mat, smat));
539d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
540d7f81bf2SJakub Kruzik }
541793850ffSBarry Smith 
5429371c9d4SSatish Balay static PetscErrorCode MatCompositeSetType_Composite(Mat mat, MatCompositeType type) {
543d7f81bf2SJakub Kruzik   Mat_Composite *b = (Mat_Composite *)mat->data;
544d7f81bf2SJakub Kruzik 
545d7f81bf2SJakub Kruzik   PetscFunctionBegin;
546ced1ac25SJakub Kruzik   b->type = type;
547d7f81bf2SJakub Kruzik   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
548f4259b30SLisandro Dalcin     mat->ops->getdiagonal   = NULL;
549d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite_Multiplicative;
550d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
55103049c21SJunchao Zhang     b->merge_mvctx          = PETSC_FALSE;
552d7f81bf2SJakub Kruzik   } else {
553d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
554d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite;
555d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite;
556793850ffSBarry Smith   }
5576d7c1e57SBarry Smith   PetscFunctionReturn(0);
5586d7c1e57SBarry Smith }
5596d7c1e57SBarry Smith 
5602c0821f3SBarry Smith /*@
5618bd739bdSJakub Kruzik    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product.
5626d7c1e57SBarry Smith 
563b2b245abSJakub Kruzik    Logically Collective on Mat
5646d7c1e57SBarry Smith 
5656d7c1e57SBarry Smith    Input Parameters:
5666d7c1e57SBarry Smith .  mat - the composite matrix
5676d7c1e57SBarry Smith 
5686d7c1e57SBarry Smith    Level: advanced
5696d7c1e57SBarry Smith 
570db781477SPatrick Sanan .seealso: `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCreateComposite()`, `MatCompositeGetType()`, `MATCOMPOSITE`
5716d7c1e57SBarry Smith 
5726d7c1e57SBarry Smith @*/
5739371c9d4SSatish Balay PetscErrorCode MatCompositeSetType(Mat mat, MatCompositeType type) {
5746d7c1e57SBarry Smith   PetscFunctionBegin;
575d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
576b2b245abSJakub Kruzik   PetscValidLogicalCollectiveEnum(mat, type, 2);
577cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeSetType_C", (Mat, MatCompositeType), (mat, type));
578793850ffSBarry Smith   PetscFunctionReturn(0);
579793850ffSBarry Smith }
580793850ffSBarry Smith 
5819371c9d4SSatish Balay static PetscErrorCode MatCompositeGetType_Composite(Mat mat, MatCompositeType *type) {
5826dbc55e5SJakub Kruzik   Mat_Composite *b = (Mat_Composite *)mat->data;
5836dbc55e5SJakub Kruzik 
5846dbc55e5SJakub Kruzik   PetscFunctionBegin;
5856dbc55e5SJakub Kruzik   *type = b->type;
5866dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
5876dbc55e5SJakub Kruzik }
5886dbc55e5SJakub Kruzik 
5896dbc55e5SJakub Kruzik /*@
5906dbc55e5SJakub Kruzik    MatCompositeGetType - Returns type of composite.
5916dbc55e5SJakub Kruzik 
5926dbc55e5SJakub Kruzik    Not Collective
5936dbc55e5SJakub Kruzik 
5946dbc55e5SJakub Kruzik    Input Parameter:
5956dbc55e5SJakub Kruzik .  mat - the composite matrix
5966dbc55e5SJakub Kruzik 
5976dbc55e5SJakub Kruzik    Output Parameter:
5986dbc55e5SJakub Kruzik .  type - type of composite
5996dbc55e5SJakub Kruzik 
6006dbc55e5SJakub Kruzik    Level: advanced
6016dbc55e5SJakub Kruzik 
602db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeSetType()`, `MATCOMPOSITE`
6036dbc55e5SJakub Kruzik 
6046dbc55e5SJakub Kruzik @*/
6059371c9d4SSatish Balay PetscErrorCode MatCompositeGetType(Mat mat, MatCompositeType *type) {
6066dbc55e5SJakub Kruzik   PetscFunctionBegin;
6076dbc55e5SJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6086dbc55e5SJakub Kruzik   PetscValidPointer(type, 2);
609cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeGetType_C", (Mat, MatCompositeType *), (mat, type));
6106dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
6116dbc55e5SJakub Kruzik }
6126dbc55e5SJakub Kruzik 
6139371c9d4SSatish Balay static PetscErrorCode MatCompositeSetMatStructure_Composite(Mat mat, MatStructure str) {
6143b35acafSJakub Kruzik   Mat_Composite *b = (Mat_Composite *)mat->data;
6153b35acafSJakub Kruzik 
6163b35acafSJakub Kruzik   PetscFunctionBegin;
6173b35acafSJakub Kruzik   b->structure = str;
6183b35acafSJakub Kruzik   PetscFunctionReturn(0);
6193b35acafSJakub Kruzik }
6203b35acafSJakub Kruzik 
6213b35acafSJakub Kruzik /*@
6223b35acafSJakub Kruzik    MatCompositeSetMatStructure - Indicates structure of matrices in the composite matrix.
6233b35acafSJakub Kruzik 
6243b35acafSJakub Kruzik    Not Collective
6253b35acafSJakub Kruzik 
6263b35acafSJakub Kruzik    Input Parameters:
6273b35acafSJakub Kruzik +  mat - the composite matrix
6283b35acafSJakub Kruzik -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN (default) or SUBSET_NONZERO_PATTERN
6293b35acafSJakub Kruzik 
6303b35acafSJakub Kruzik    Level: advanced
6313b35acafSJakub Kruzik 
6323b35acafSJakub Kruzik    Notes:
6333b35acafSJakub Kruzik     Information about the matrices structure is used in MatCompositeMerge() for additive composite matrix.
6343b35acafSJakub Kruzik 
635db781477SPatrick Sanan .seealso: `MatAXPY()`, `MatCreateComposite()`, `MatCompositeMerge()` `MatCompositeGetMatStructure()`, `MATCOMPOSITE`
6363b35acafSJakub Kruzik 
6373b35acafSJakub Kruzik @*/
6389371c9d4SSatish Balay PetscErrorCode MatCompositeSetMatStructure(Mat mat, MatStructure str) {
6393b35acafSJakub Kruzik   PetscFunctionBegin;
6403b35acafSJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
641cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeSetMatStructure_C", (Mat, MatStructure), (mat, str));
6423b35acafSJakub Kruzik   PetscFunctionReturn(0);
6433b35acafSJakub Kruzik }
6443b35acafSJakub Kruzik 
6459371c9d4SSatish Balay static PetscErrorCode MatCompositeGetMatStructure_Composite(Mat mat, MatStructure *str) {
6463b35acafSJakub Kruzik   Mat_Composite *b = (Mat_Composite *)mat->data;
6473b35acafSJakub Kruzik 
6483b35acafSJakub Kruzik   PetscFunctionBegin;
6493b35acafSJakub Kruzik   *str = b->structure;
6503b35acafSJakub Kruzik   PetscFunctionReturn(0);
6513b35acafSJakub Kruzik }
6523b35acafSJakub Kruzik 
6533b35acafSJakub Kruzik /*@
6543b35acafSJakub Kruzik    MatCompositeGetMatStructure - Returns the structure of matrices in the composite matrix.
6553b35acafSJakub Kruzik 
6563b35acafSJakub Kruzik    Not Collective
6573b35acafSJakub Kruzik 
6583b35acafSJakub Kruzik    Input Parameter:
6593b35acafSJakub Kruzik .  mat - the composite matrix
6603b35acafSJakub Kruzik 
6613b35acafSJakub Kruzik    Output Parameter:
6623b35acafSJakub Kruzik .  str - structure of the matrices
6633b35acafSJakub Kruzik 
6643b35acafSJakub Kruzik    Level: advanced
6653b35acafSJakub Kruzik 
666db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeSetMatStructure()`, `MATCOMPOSITE`
6673b35acafSJakub Kruzik 
6683b35acafSJakub Kruzik @*/
6699371c9d4SSatish Balay PetscErrorCode MatCompositeGetMatStructure(Mat mat, MatStructure *str) {
6703b35acafSJakub Kruzik   PetscFunctionBegin;
6713b35acafSJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6723b35acafSJakub Kruzik   PetscValidPointer(str, 2);
673cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeGetMatStructure_C", (Mat, MatStructure *), (mat, str));
6743b35acafSJakub Kruzik   PetscFunctionReturn(0);
6753b35acafSJakub Kruzik }
6763b35acafSJakub Kruzik 
6779371c9d4SSatish Balay static PetscErrorCode MatCompositeSetMergeType_Composite(Mat mat, MatCompositeMergeType type) {
6788c8613bfSJakub Kruzik   Mat_Composite *shell = (Mat_Composite *)mat->data;
6798c8613bfSJakub Kruzik 
6808c8613bfSJakub Kruzik   PetscFunctionBegin;
6818c8613bfSJakub Kruzik   shell->mergetype = type;
6828c8613bfSJakub Kruzik   PetscFunctionReturn(0);
6838c8613bfSJakub Kruzik }
6848c8613bfSJakub Kruzik 
6858c8613bfSJakub Kruzik /*@
6868c8613bfSJakub Kruzik    MatCompositeSetMergeType - Sets order of MatCompositeMerge().
6878c8613bfSJakub Kruzik 
6888c8613bfSJakub Kruzik    Logically Collective on Mat
6898c8613bfSJakub Kruzik 
690d8d19677SJose E. Roman    Input Parameters:
6918c8613bfSJakub Kruzik +  mat - the composite matrix
6928c8613bfSJakub Kruzik -  type - MAT_COMPOSITE_MERGE RIGHT (default) to start merge from right with the first added matrix (mat[0]),
6938c8613bfSJakub Kruzik           MAT_COMPOSITE_MERGE_LEFT to start merge from left with the last added matrix (mat[nmat-1])
6948c8613bfSJakub Kruzik 
6958c8613bfSJakub Kruzik    Level: advanced
6968c8613bfSJakub Kruzik 
6978c8613bfSJakub Kruzik    Notes:
6988c8613bfSJakub Kruzik     The resulting matrix is the same regardles of the MergeType. Only the order of operation is changed.
6998c8613bfSJakub Kruzik     If set to MAT_COMPOSITE_MERGE_RIGHT the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0])))
7008c8613bfSJakub Kruzik     otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0].
7018c8613bfSJakub Kruzik 
702db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeMerge()`, `MATCOMPOSITE`
7038c8613bfSJakub Kruzik 
7048c8613bfSJakub Kruzik @*/
7059371c9d4SSatish Balay PetscErrorCode MatCompositeSetMergeType(Mat mat, MatCompositeMergeType type) {
7068c8613bfSJakub Kruzik   PetscFunctionBegin;
7078c8613bfSJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7088c8613bfSJakub Kruzik   PetscValidLogicalCollectiveEnum(mat, type, 2);
709cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeSetMergeType_C", (Mat, MatCompositeMergeType), (mat, type));
7108c8613bfSJakub Kruzik   PetscFunctionReturn(0);
7118c8613bfSJakub Kruzik }
7128c8613bfSJakub Kruzik 
7139371c9d4SSatish Balay static PetscErrorCode MatCompositeMerge_Composite(Mat mat) {
714b52f573bSBarry Smith   Mat_Composite    *shell = (Mat_Composite *)mat->data;
7156d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head, prev = shell->tail;
7166d7c1e57SBarry Smith   Mat               tmat, newmat;
7171ba60692SJed Brown   Vec               left, right;
7181ba60692SJed Brown   PetscScalar       scale;
71903049c21SJunchao Zhang   PetscInt          i;
720b52f573bSBarry Smith 
721b52f573bSBarry Smith   PetscFunctionBegin;
72228b400f6SJacob Faibussowitsch   PetscCheck(next, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least one matrix with MatCompositeAddMat()");
72303049c21SJunchao Zhang   scale = shell->scale;
7246d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
7258c8613bfSJakub Kruzik     if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) {
72603049c21SJunchao Zhang       i = 0;
7279566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(next->mat, MAT_COPY_VALUES, &tmat));
7289566063dSJacob Faibussowitsch       if (shell->scalings) PetscCall(MatScale(tmat, shell->scalings[i++]));
729*48a46eb9SPierre Jolivet       while ((next = next->next)) PetscCall(MatAXPY(tmat, (shell->scalings ? shell->scalings[i++] : 1.0), next->mat, shell->structure));
7306d7c1e57SBarry Smith     } else {
73103049c21SJunchao Zhang       i = shell->nmat - 1;
7329566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(prev->mat, MAT_COPY_VALUES, &tmat));
7339566063dSJacob Faibussowitsch       if (shell->scalings) PetscCall(MatScale(tmat, shell->scalings[i--]));
734*48a46eb9SPierre Jolivet       while ((prev = prev->prev)) PetscCall(MatAXPY(tmat, (shell->scalings ? shell->scalings[i--] : 1.0), prev->mat, shell->structure));
7358c8613bfSJakub Kruzik     }
7368c8613bfSJakub Kruzik   } else {
7378c8613bfSJakub Kruzik     if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) {
7389566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(next->mat, MAT_COPY_VALUES, &tmat));
739b6cfcaf5SJakub Kruzik       while ((next = next->next)) {
7409566063dSJacob Faibussowitsch         PetscCall(MatMatMult(next->mat, tmat, MAT_INITIAL_MATRIX, PETSC_DECIDE, &newmat));
7419566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&tmat));
7426d7c1e57SBarry Smith         tmat = newmat;
7436d7c1e57SBarry Smith       }
74404d534ceSJakub Kruzik     } else {
7459566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(prev->mat, MAT_COPY_VALUES, &tmat));
74604d534ceSJakub Kruzik       while ((prev = prev->prev)) {
7479566063dSJacob Faibussowitsch         PetscCall(MatMatMult(tmat, prev->mat, MAT_INITIAL_MATRIX, PETSC_DECIDE, &newmat));
7489566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&tmat));
74904d534ceSJakub Kruzik         tmat = newmat;
75004d534ceSJakub Kruzik       }
75104d534ceSJakub Kruzik     }
7529371c9d4SSatish Balay     if (shell->scalings) {
7539371c9d4SSatish Balay       for (i = 0; i < shell->nmat; i++) scale *= shell->scalings[i];
7549371c9d4SSatish Balay     }
7556d7c1e57SBarry Smith   }
7561ba60692SJed Brown 
7579566063dSJacob Faibussowitsch   if ((left = shell->left)) PetscCall(PetscObjectReference((PetscObject)left));
7589566063dSJacob Faibussowitsch   if ((right = shell->right)) PetscCall(PetscObjectReference((PetscObject)right));
7591ba60692SJed Brown 
7609566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(mat, &tmat));
7611ba60692SJed Brown 
7629566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(mat, left, right));
7639566063dSJacob Faibussowitsch   PetscCall(MatScale(mat, scale));
7649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&left));
7659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&right));
766b52f573bSBarry Smith   PetscFunctionReturn(0);
767b52f573bSBarry Smith }
7686a7ede75SJakub Kruzik 
7696a7ede75SJakub Kruzik /*@
770d7f81bf2SJakub Kruzik    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
7718bd739bdSJakub Kruzik      by summing or computing the product of all the matrices inside the composite matrix.
772d7f81bf2SJakub Kruzik 
773b2b245abSJakub Kruzik   Collective
774d7f81bf2SJakub Kruzik 
775f899ff85SJose E. Roman    Input Parameter:
776d7f81bf2SJakub Kruzik .  mat - the composite matrix
777d7f81bf2SJakub Kruzik 
7784b2558d6SJakub Kruzik    Options Database Keys:
779b28d0daaSJakub Kruzik +  -mat_composite_merge - merge in MatAssemblyEnd()
780b28d0daaSJakub Kruzik -  -mat_composite_merge_type - set merge direction
781d7f81bf2SJakub Kruzik 
782d7f81bf2SJakub Kruzik    Level: advanced
783d7f81bf2SJakub Kruzik 
784d7f81bf2SJakub Kruzik    Notes:
785d7f81bf2SJakub Kruzik       The MatType of the resulting matrix will be the same as the MatType of the FIRST
786d7f81bf2SJakub Kruzik     matrix in the composite matrix.
787d7f81bf2SJakub Kruzik 
788db781477SPatrick Sanan .seealso: `MatDestroy()`, `MatMult()`, `MatCompositeAddMat()`, `MatCreateComposite()`, `MatCompositeSetMatStructure()`, `MatCompositeSetMergeType()`, `MATCOMPOSITE`
789d7f81bf2SJakub Kruzik 
790d7f81bf2SJakub Kruzik @*/
7919371c9d4SSatish Balay PetscErrorCode MatCompositeMerge(Mat mat) {
792d7f81bf2SJakub Kruzik   PetscFunctionBegin;
793d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
794cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeMerge_C", (Mat), (mat));
795d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
796d7f81bf2SJakub Kruzik }
797d7f81bf2SJakub Kruzik 
7989371c9d4SSatish Balay static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat, PetscInt *nmat) {
799d7f81bf2SJakub Kruzik   Mat_Composite *shell = (Mat_Composite *)mat->data;
800d7f81bf2SJakub Kruzik 
801d7f81bf2SJakub Kruzik   PetscFunctionBegin;
802d7f81bf2SJakub Kruzik   *nmat = shell->nmat;
803d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
804d7f81bf2SJakub Kruzik }
805d7f81bf2SJakub Kruzik 
806d7f81bf2SJakub Kruzik /*@
8076d0add67SJakub Kruzik    MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix.
8086a7ede75SJakub Kruzik 
8096a7ede75SJakub Kruzik    Not Collective
8106a7ede75SJakub Kruzik 
8116a7ede75SJakub Kruzik    Input Parameter:
812d7f81bf2SJakub Kruzik .  mat - the composite matrix
8136a7ede75SJakub Kruzik 
8146a7ede75SJakub Kruzik    Output Parameter:
8156d0add67SJakub Kruzik .  nmat - number of matrices in the composite matrix
8166a7ede75SJakub Kruzik 
8178b5c3584SJakub Kruzik    Level: advanced
8186a7ede75SJakub Kruzik 
819db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeGetMat()`, `MATCOMPOSITE`
8206a7ede75SJakub Kruzik 
8216a7ede75SJakub Kruzik @*/
8229371c9d4SSatish Balay PetscErrorCode MatCompositeGetNumberMat(Mat mat, PetscInt *nmat) {
8236a7ede75SJakub Kruzik   PetscFunctionBegin;
824d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
825dadcf809SJacob Faibussowitsch   PetscValidIntPointer(nmat, 2);
826cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeGetNumberMat_C", (Mat, PetscInt *), (mat, nmat));
827d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
828d7f81bf2SJakub Kruzik }
829d7f81bf2SJakub Kruzik 
8309371c9d4SSatish Balay static PetscErrorCode MatCompositeGetMat_Composite(Mat mat, PetscInt i, Mat *Ai) {
831d7f81bf2SJakub Kruzik   Mat_Composite    *shell = (Mat_Composite *)mat->data;
832d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink;
833d7f81bf2SJakub Kruzik   PetscInt          k;
834d7f81bf2SJakub Kruzik 
835d7f81bf2SJakub Kruzik   PetscFunctionBegin;
83608401ef6SPierre Jolivet   PetscCheck(i < shell->nmat, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "index out of range: %" PetscInt_FMT " >= %" PetscInt_FMT, i, shell->nmat);
837d7f81bf2SJakub Kruzik   ilink = shell->head;
8389371c9d4SSatish Balay   for (k = 0; k < i; k++) { ilink = ilink->next; }
839d7f81bf2SJakub Kruzik   *Ai = ilink->mat;
8406a7ede75SJakub Kruzik   PetscFunctionReturn(0);
8416a7ede75SJakub Kruzik }
8426a7ede75SJakub Kruzik 
8438b5c3584SJakub Kruzik /*@
8448bd739bdSJakub Kruzik    MatCompositeGetMat - Returns the ith matrix from the composite matrix.
8458b5c3584SJakub Kruzik 
8468b5c3584SJakub Kruzik    Logically Collective on Mat
8478b5c3584SJakub Kruzik 
848d8d19677SJose E. Roman    Input Parameters:
849d7f81bf2SJakub Kruzik +  mat - the composite matrix
8508b5c3584SJakub Kruzik -  i - the number of requested matrix
8518b5c3584SJakub Kruzik 
8528b5c3584SJakub Kruzik    Output Parameter:
8538b5c3584SJakub Kruzik .  Ai - ith matrix in composite
8548b5c3584SJakub Kruzik 
8558b5c3584SJakub Kruzik    Level: advanced
8568b5c3584SJakub Kruzik 
857db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeGetNumberMat()`, `MatCompositeAddMat()`, `MATCOMPOSITE`
8588b5c3584SJakub Kruzik 
8598b5c3584SJakub Kruzik @*/
8609371c9d4SSatish Balay PetscErrorCode MatCompositeGetMat(Mat mat, PetscInt i, Mat *Ai) {
8618b5c3584SJakub Kruzik   PetscFunctionBegin;
862d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
863d7f81bf2SJakub Kruzik   PetscValidLogicalCollectiveInt(mat, i, 2);
8648b5c3584SJakub Kruzik   PetscValidPointer(Ai, 3);
865cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeGetMat_C", (Mat, PetscInt, Mat *), (mat, i, Ai));
8668b5c3584SJakub Kruzik   PetscFunctionReturn(0);
8678b5c3584SJakub Kruzik }
8688b5c3584SJakub Kruzik 
8699371c9d4SSatish Balay PetscErrorCode MatCompositeSetScalings_Composite(Mat mat, const PetscScalar *scalings) {
87003049c21SJunchao Zhang   Mat_Composite *shell = (Mat_Composite *)mat->data;
87103049c21SJunchao Zhang   PetscInt       nmat;
87203049c21SJunchao Zhang 
87303049c21SJunchao Zhang   PetscFunctionBegin;
8749566063dSJacob Faibussowitsch   PetscCall(MatCompositeGetNumberMat(mat, &nmat));
8759566063dSJacob Faibussowitsch   if (!shell->scalings) PetscCall(PetscMalloc1(nmat, &shell->scalings));
8769566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(shell->scalings, scalings, nmat));
87703049c21SJunchao Zhang   PetscFunctionReturn(0);
87803049c21SJunchao Zhang }
87903049c21SJunchao Zhang 
88003049c21SJunchao Zhang /*@
88103049c21SJunchao Zhang    MatCompositeSetScalings - Sets separate scaling factors for component matrices.
88203049c21SJunchao Zhang 
88303049c21SJunchao Zhang    Logically Collective on Mat
88403049c21SJunchao Zhang 
885d8d19677SJose E. Roman    Input Parameters:
88603049c21SJunchao Zhang +  mat      - the composite matrix
88703049c21SJunchao Zhang -  scalings - array of scaling factors with scalings[i] being factor of i-th matrix, for i in [0, nmat)
88803049c21SJunchao Zhang 
88903049c21SJunchao Zhang    Level: advanced
89003049c21SJunchao Zhang 
891db781477SPatrick Sanan .seealso: `MatScale()`, `MatDiagonalScale()`, `MATCOMPOSITE`
89203049c21SJunchao Zhang 
89303049c21SJunchao Zhang @*/
8949371c9d4SSatish Balay PetscErrorCode MatCompositeSetScalings(Mat mat, const PetscScalar *scalings) {
89503049c21SJunchao Zhang   PetscFunctionBegin;
89603049c21SJunchao Zhang   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
897dadcf809SJacob Faibussowitsch   PetscValidScalarPointer(scalings, 2);
89803049c21SJunchao Zhang   PetscValidLogicalCollectiveScalar(mat, *scalings, 2);
899cac4c232SBarry Smith   PetscUseMethod(mat, "MatCompositeSetScalings_C", (Mat, const PetscScalar *), (mat, scalings));
90003049c21SJunchao Zhang   PetscFunctionReturn(0);
90103049c21SJunchao Zhang }
90203049c21SJunchao Zhang 
903f4259b30SLisandro Dalcin static struct _MatOps MatOps_Values = {NULL,
904f4259b30SLisandro Dalcin                                        NULL,
905f4259b30SLisandro Dalcin                                        NULL,
90641cd0125SJakub Kruzik                                        MatMult_Composite,
9077bf3a71bSJakub Kruzik                                        MatMultAdd_Composite,
90841cd0125SJakub Kruzik                                        /*  5*/ MatMultTranspose_Composite,
9097bf3a71bSJakub Kruzik                                        MatMultTransposeAdd_Composite,
910f4259b30SLisandro Dalcin                                        NULL,
911f4259b30SLisandro Dalcin                                        NULL,
912f4259b30SLisandro Dalcin                                        NULL,
913f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
914f4259b30SLisandro Dalcin                                        NULL,
915f4259b30SLisandro Dalcin                                        NULL,
916f4259b30SLisandro Dalcin                                        NULL,
917f4259b30SLisandro Dalcin                                        NULL,
918f4259b30SLisandro Dalcin                                        /* 15*/ NULL,
919f4259b30SLisandro Dalcin                                        NULL,
92041cd0125SJakub Kruzik                                        MatGetDiagonal_Composite,
92141cd0125SJakub Kruzik                                        MatDiagonalScale_Composite,
922f4259b30SLisandro Dalcin                                        NULL,
923f4259b30SLisandro Dalcin                                        /* 20*/ NULL,
92441cd0125SJakub Kruzik                                        MatAssemblyEnd_Composite,
925f4259b30SLisandro Dalcin                                        NULL,
926f4259b30SLisandro Dalcin                                        NULL,
927f4259b30SLisandro Dalcin                                        /* 24*/ NULL,
928f4259b30SLisandro Dalcin                                        NULL,
929f4259b30SLisandro Dalcin                                        NULL,
930f4259b30SLisandro Dalcin                                        NULL,
931f4259b30SLisandro Dalcin                                        NULL,
932f4259b30SLisandro Dalcin                                        /* 29*/ NULL,
933f4259b30SLisandro Dalcin                                        NULL,
934f4259b30SLisandro Dalcin                                        NULL,
935f4259b30SLisandro Dalcin                                        NULL,
936f4259b30SLisandro Dalcin                                        NULL,
937f4259b30SLisandro Dalcin                                        /* 34*/ NULL,
938f4259b30SLisandro Dalcin                                        NULL,
939f4259b30SLisandro Dalcin                                        NULL,
940f4259b30SLisandro Dalcin                                        NULL,
941f4259b30SLisandro Dalcin                                        NULL,
942f4259b30SLisandro Dalcin                                        /* 39*/ NULL,
943f4259b30SLisandro Dalcin                                        NULL,
944f4259b30SLisandro Dalcin                                        NULL,
945f4259b30SLisandro Dalcin                                        NULL,
946f4259b30SLisandro Dalcin                                        NULL,
947f4259b30SLisandro Dalcin                                        /* 44*/ NULL,
94841cd0125SJakub Kruzik                                        MatScale_Composite,
94941cd0125SJakub Kruzik                                        MatShift_Basic,
950f4259b30SLisandro Dalcin                                        NULL,
951f4259b30SLisandro Dalcin                                        NULL,
952f4259b30SLisandro Dalcin                                        /* 49*/ NULL,
953f4259b30SLisandro Dalcin                                        NULL,
954f4259b30SLisandro Dalcin                                        NULL,
955f4259b30SLisandro Dalcin                                        NULL,
956f4259b30SLisandro Dalcin                                        NULL,
957f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
958f4259b30SLisandro Dalcin                                        NULL,
959f4259b30SLisandro Dalcin                                        NULL,
960f4259b30SLisandro Dalcin                                        NULL,
961f4259b30SLisandro Dalcin                                        NULL,
962f4259b30SLisandro Dalcin                                        /* 59*/ NULL,
96341cd0125SJakub Kruzik                                        MatDestroy_Composite,
964f4259b30SLisandro Dalcin                                        NULL,
965f4259b30SLisandro Dalcin                                        NULL,
966f4259b30SLisandro Dalcin                                        NULL,
967f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
968f4259b30SLisandro Dalcin                                        NULL,
969f4259b30SLisandro Dalcin                                        NULL,
970f4259b30SLisandro Dalcin                                        NULL,
971f4259b30SLisandro Dalcin                                        NULL,
972f4259b30SLisandro Dalcin                                        /* 69*/ NULL,
973f4259b30SLisandro Dalcin                                        NULL,
974f4259b30SLisandro Dalcin                                        NULL,
975f4259b30SLisandro Dalcin                                        NULL,
976f4259b30SLisandro Dalcin                                        NULL,
977f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
978f4259b30SLisandro Dalcin                                        NULL,
9794b2558d6SJakub Kruzik                                        MatSetFromOptions_Composite,
980f4259b30SLisandro Dalcin                                        NULL,
981f4259b30SLisandro Dalcin                                        NULL,
982f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
983f4259b30SLisandro Dalcin                                        NULL,
984f4259b30SLisandro Dalcin                                        NULL,
985f4259b30SLisandro Dalcin                                        NULL,
986f4259b30SLisandro Dalcin                                        NULL,
987f4259b30SLisandro Dalcin                                        /* 84*/ NULL,
988f4259b30SLisandro Dalcin                                        NULL,
989f4259b30SLisandro Dalcin                                        NULL,
990f4259b30SLisandro Dalcin                                        NULL,
991f4259b30SLisandro Dalcin                                        NULL,
992f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
993f4259b30SLisandro Dalcin                                        NULL,
994f4259b30SLisandro Dalcin                                        NULL,
995f4259b30SLisandro Dalcin                                        NULL,
996f4259b30SLisandro Dalcin                                        NULL,
997f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
998f4259b30SLisandro Dalcin                                        NULL,
999f4259b30SLisandro Dalcin                                        NULL,
1000f4259b30SLisandro Dalcin                                        NULL,
1001f4259b30SLisandro Dalcin                                        NULL,
1002f4259b30SLisandro Dalcin                                        /*99*/ NULL,
1003f4259b30SLisandro Dalcin                                        NULL,
1004f4259b30SLisandro Dalcin                                        NULL,
1005f4259b30SLisandro Dalcin                                        NULL,
1006f4259b30SLisandro Dalcin                                        NULL,
1007f4259b30SLisandro Dalcin                                        /*104*/ NULL,
1008f4259b30SLisandro Dalcin                                        NULL,
1009f4259b30SLisandro Dalcin                                        NULL,
1010f4259b30SLisandro Dalcin                                        NULL,
1011f4259b30SLisandro Dalcin                                        NULL,
1012f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1013f4259b30SLisandro Dalcin                                        NULL,
1014f4259b30SLisandro Dalcin                                        NULL,
1015f4259b30SLisandro Dalcin                                        NULL,
1016f4259b30SLisandro Dalcin                                        NULL,
1017f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1018f4259b30SLisandro Dalcin                                        NULL,
1019f4259b30SLisandro Dalcin                                        NULL,
1020f4259b30SLisandro Dalcin                                        NULL,
1021f4259b30SLisandro Dalcin                                        NULL,
1022f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1023f4259b30SLisandro Dalcin                                        NULL,
1024f4259b30SLisandro Dalcin                                        NULL,
1025f4259b30SLisandro Dalcin                                        NULL,
1026f4259b30SLisandro Dalcin                                        NULL,
1027f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1028f4259b30SLisandro Dalcin                                        NULL,
1029f4259b30SLisandro Dalcin                                        NULL,
1030f4259b30SLisandro Dalcin                                        NULL,
1031f4259b30SLisandro Dalcin                                        NULL,
1032f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1033f4259b30SLisandro Dalcin                                        NULL,
1034f4259b30SLisandro Dalcin                                        NULL,
1035f4259b30SLisandro Dalcin                                        NULL,
1036f4259b30SLisandro Dalcin                                        NULL,
1037f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1038f4259b30SLisandro Dalcin                                        NULL,
1039f4259b30SLisandro Dalcin                                        NULL,
1040f4259b30SLisandro Dalcin                                        NULL,
1041f4259b30SLisandro Dalcin                                        NULL,
1042f4259b30SLisandro Dalcin                                        /*139*/ NULL,
1043f4259b30SLisandro Dalcin                                        NULL,
1044d70f29a3SPierre Jolivet                                        NULL,
1045d70f29a3SPierre Jolivet                                        NULL,
1046d70f29a3SPierre Jolivet                                        NULL,
1047d70f29a3SPierre Jolivet                                        /*144*/ NULL,
1048d70f29a3SPierre Jolivet                                        NULL,
1049d70f29a3SPierre Jolivet                                        NULL,
105099a7f59eSMark Adams                                        NULL,
105199a7f59eSMark Adams                                        NULL,
10527fb60732SBarry Smith                                        NULL,
10539371c9d4SSatish Balay                                        /*150*/ NULL};
105441cd0125SJakub Kruzik 
105541cd0125SJakub Kruzik /*MC
105641cd0125SJakub Kruzik    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices.
105741cd0125SJakub Kruzik     The matrices need to have a correct size and parallel layout for the sum or product to be valid.
105841cd0125SJakub Kruzik 
105941cd0125SJakub Kruzik    Notes:
106041cd0125SJakub Kruzik     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
106141cd0125SJakub Kruzik 
106241cd0125SJakub Kruzik   Level: advanced
106341cd0125SJakub Kruzik 
1064db781477SPatrick Sanan .seealso: `MatCreateComposite()`, `MatCompositeSetScalings()`, `MatCompositeAddMat()`, `MatSetType()`, `MatCompositeSetType()`, `MatCompositeGetType()`, `MatCompositeSetMatStructure()`, `MatCompositeGetMatStructure()`, `MatCompositeMerge()`, `MatCompositeSetMergeType()`, `MatCompositeGetNumberMat()`, `MatCompositeGetMat()`
106541cd0125SJakub Kruzik M*/
106641cd0125SJakub Kruzik 
10679371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) {
106841cd0125SJakub Kruzik   Mat_Composite *b;
106941cd0125SJakub Kruzik 
107041cd0125SJakub Kruzik   PetscFunctionBegin;
10719566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(A, &b));
107241cd0125SJakub Kruzik   A->data = (void *)b;
10739566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A->ops, &MatOps_Values, sizeof(struct _MatOps)));
107441cd0125SJakub Kruzik 
10759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
10769566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
107741cd0125SJakub Kruzik 
107841cd0125SJakub Kruzik   A->assembled    = PETSC_TRUE;
107941cd0125SJakub Kruzik   A->preallocated = PETSC_TRUE;
108041cd0125SJakub Kruzik   b->type         = MAT_COMPOSITE_ADDITIVE;
108141cd0125SJakub Kruzik   b->scale        = 1.0;
108241cd0125SJakub Kruzik   b->nmat         = 0;
10834b2558d6SJakub Kruzik   b->merge        = PETSC_FALSE;
10848c8613bfSJakub Kruzik   b->mergetype    = MAT_COMPOSITE_MERGE_RIGHT;
10853b35acafSJakub Kruzik   b->structure    = DIFFERENT_NONZERO_PATTERN;
108603049c21SJunchao Zhang   b->merge_mvctx  = PETSC_TRUE;
108703049c21SJunchao Zhang 
10889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeAddMat_C", MatCompositeAddMat_Composite));
10899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetType_C", MatCompositeSetType_Composite));
10909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetType_C", MatCompositeGetType_Composite));
10919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetMergeType_C", MatCompositeSetMergeType_Composite));
10929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetMatStructure_C", MatCompositeSetMatStructure_Composite));
10939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetMatStructure_C", MatCompositeGetMatStructure_Composite));
10949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeMerge_C", MatCompositeMerge_Composite));
10959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetNumberMat_C", MatCompositeGetNumberMat_Composite));
10969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeGetMat_C", MatCompositeGetMat_Composite));
10979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatCompositeSetScalings_C", MatCompositeSetScalings_Composite));
109841cd0125SJakub Kruzik 
10999566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATCOMPOSITE));
110041cd0125SJakub Kruzik   PetscFunctionReturn(0);
110141cd0125SJakub Kruzik }
1102