xref: /petsc/src/mat/impls/composite/mcomposite.c (revision d083f849a86f1f43e18d534ee43954e2786cb29a)
1793850ffSBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
3793850ffSBarry Smith 
48c8613bfSJakub Kruzik const char *const MatCompositeMergeTypes[] = {"left","right","MatCompositeMergeType","MAT_COMPOSITE_",0};
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() */
19e4fc5df0SBarry Smith   Vec                   leftwork,rightwork;
206a7ede75SJakub Kruzik   PetscInt              nmat;
214b2558d6SJakub Kruzik   PetscBool             merge;
228c8613bfSJakub Kruzik   MatCompositeMergeType mergetype;
233b35acafSJakub Kruzik   MatStructure          structure;
24793850ffSBarry Smith } Mat_Composite;
25793850ffSBarry Smith 
26793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
27793850ffSBarry Smith {
28793850ffSBarry Smith   PetscErrorCode    ierr;
292c33bbaeSSatish Balay   Mat_Composite     *shell = (Mat_Composite*)mat->data;
306d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head,oldnext;
31793850ffSBarry Smith 
32793850ffSBarry Smith   PetscFunctionBegin;
33793850ffSBarry Smith   while (next) {
346bf464f9SBarry Smith     ierr = MatDestroy(&next->mat);CHKERRQ(ierr);
356d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
366bf464f9SBarry Smith       ierr = VecDestroy(&next->work);CHKERRQ(ierr);
376d7c1e57SBarry Smith     }
386d7c1e57SBarry Smith     oldnext = next;
39793850ffSBarry Smith     next    = next->next;
406d7c1e57SBarry Smith     ierr    = PetscFree(oldnext);CHKERRQ(ierr);
41793850ffSBarry Smith   }
426bf464f9SBarry Smith   ierr = VecDestroy(&shell->work);CHKERRQ(ierr);
436bf464f9SBarry Smith   ierr = VecDestroy(&shell->left);CHKERRQ(ierr);
446bf464f9SBarry Smith   ierr = VecDestroy(&shell->right);CHKERRQ(ierr);
456bf464f9SBarry Smith   ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr);
466bf464f9SBarry Smith   ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr);
476bf464f9SBarry Smith   ierr = PetscFree(mat->data);CHKERRQ(ierr);
48793850ffSBarry Smith   PetscFunctionReturn(0);
49793850ffSBarry Smith }
50793850ffSBarry Smith 
516d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
526d7c1e57SBarry Smith {
536d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
546d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head;
556d7c1e57SBarry Smith   PetscErrorCode    ierr;
566d7c1e57SBarry Smith   Vec               in,out;
576d7c1e57SBarry Smith 
586d7c1e57SBarry Smith   PetscFunctionBegin;
59e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
606d7c1e57SBarry Smith   in = x;
61e4fc5df0SBarry Smith   if (shell->right) {
62e4fc5df0SBarry Smith     if (!shell->rightwork) {
63e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
64e4fc5df0SBarry Smith     }
65e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
66e4fc5df0SBarry Smith     in   = shell->rightwork;
67e4fc5df0SBarry Smith   }
686d7c1e57SBarry Smith   while (next->next) {
696d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
702a7a6963SBarry Smith       ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr);
716d7c1e57SBarry Smith     }
726d7c1e57SBarry Smith     out  = next->work;
736d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
746d7c1e57SBarry Smith     in   = out;
756d7c1e57SBarry Smith     next = next->next;
766d7c1e57SBarry Smith   }
776d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
78e4fc5df0SBarry Smith   if (shell->left) {
79e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
80e4fc5df0SBarry Smith   }
81e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
826d7c1e57SBarry Smith   PetscFunctionReturn(0);
836d7c1e57SBarry Smith }
846d7c1e57SBarry Smith 
856d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
866d7c1e57SBarry Smith {
876d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
886d7c1e57SBarry Smith   Mat_CompositeLink tail   = shell->tail;
896d7c1e57SBarry Smith   PetscErrorCode    ierr;
906d7c1e57SBarry Smith   Vec               in,out;
916d7c1e57SBarry Smith 
926d7c1e57SBarry Smith   PetscFunctionBegin;
93e32f2f54SBarry Smith   if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
946d7c1e57SBarry Smith   in = x;
95e4fc5df0SBarry Smith   if (shell->left) {
96e4fc5df0SBarry Smith     if (!shell->leftwork) {
97e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
98e4fc5df0SBarry Smith     }
99e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
100e4fc5df0SBarry Smith     in   = shell->leftwork;
101e4fc5df0SBarry Smith   }
1026d7c1e57SBarry Smith   while (tail->prev) {
1036d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
1042a7a6963SBarry Smith       ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr);
1056d7c1e57SBarry Smith     }
1066d7c1e57SBarry Smith     out  = tail->prev->work;
1076d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
1086d7c1e57SBarry Smith     in   = out;
1096d7c1e57SBarry Smith     tail = tail->prev;
1106d7c1e57SBarry Smith   }
1116d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
112e4fc5df0SBarry Smith   if (shell->right) {
113e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
114e4fc5df0SBarry Smith   }
115e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
1166d7c1e57SBarry Smith   PetscFunctionReturn(0);
1176d7c1e57SBarry Smith }
1186d7c1e57SBarry Smith 
119793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
120793850ffSBarry Smith {
121793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
122793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
123793850ffSBarry Smith   PetscErrorCode    ierr;
124e4fc5df0SBarry Smith   Vec               in;
125793850ffSBarry Smith 
126793850ffSBarry Smith   PetscFunctionBegin;
127e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
128e4fc5df0SBarry Smith   in = x;
129e4fc5df0SBarry Smith   if (shell->right) {
130e4fc5df0SBarry Smith     if (!shell->rightwork) {
131e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
132793850ffSBarry Smith     }
133e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
134e4fc5df0SBarry Smith     in   = shell->rightwork;
135e4fc5df0SBarry Smith   }
136e4fc5df0SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
137e4fc5df0SBarry Smith   while ((next = next->next)) {
138e4fc5df0SBarry Smith     ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr);
139e4fc5df0SBarry Smith   }
140e4fc5df0SBarry Smith   if (shell->left) {
141e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
142e4fc5df0SBarry Smith   }
143e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
144793850ffSBarry Smith   PetscFunctionReturn(0);
145793850ffSBarry Smith }
146793850ffSBarry Smith 
147793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
148793850ffSBarry Smith {
149793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
150793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
151793850ffSBarry Smith   PetscErrorCode    ierr;
152e4fc5df0SBarry Smith   Vec               in;
153793850ffSBarry Smith 
154793850ffSBarry Smith   PetscFunctionBegin;
155e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
156e4fc5df0SBarry Smith   in = x;
157e4fc5df0SBarry Smith   if (shell->left) {
158e4fc5df0SBarry Smith     if (!shell->leftwork) {
159e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
160793850ffSBarry Smith     }
161e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
162e4fc5df0SBarry Smith     in   = shell->leftwork;
163e4fc5df0SBarry Smith   }
164e4fc5df0SBarry Smith   ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr);
165e4fc5df0SBarry Smith   while ((next = next->next)) {
166e4fc5df0SBarry Smith     ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr);
167e4fc5df0SBarry Smith   }
168e4fc5df0SBarry Smith   if (shell->right) {
169e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
170e4fc5df0SBarry Smith   }
171e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
172793850ffSBarry Smith   PetscFunctionReturn(0);
173793850ffSBarry Smith }
174793850ffSBarry Smith 
1757bf3a71bSJakub Kruzik PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z)
1767bf3a71bSJakub Kruzik {
1777bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1787bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1797bf3a71bSJakub Kruzik 
1807bf3a71bSJakub Kruzik   PetscFunctionBegin;
1817bf3a71bSJakub Kruzik   if (y != z) {
1827bf3a71bSJakub Kruzik     ierr = MatMult(A,x,z);CHKERRQ(ierr);
1837bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
1847bf3a71bSJakub Kruzik   } else {
1857bf3a71bSJakub Kruzik     if (!shell->leftwork) {
1867bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr);
1877bf3a71bSJakub Kruzik     }
1887bf3a71bSJakub Kruzik     ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr);
1897bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
1907bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr);
1917bf3a71bSJakub Kruzik   }
1927bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
1937bf3a71bSJakub Kruzik }
1947bf3a71bSJakub Kruzik 
1957bf3a71bSJakub Kruzik PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z)
1967bf3a71bSJakub Kruzik {
1977bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1987bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1997bf3a71bSJakub Kruzik 
2007bf3a71bSJakub Kruzik   PetscFunctionBegin;
2017bf3a71bSJakub Kruzik   if (y != z) {
2027bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr);
2037bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
2047bf3a71bSJakub Kruzik   } else {
2057bf3a71bSJakub Kruzik     if (!shell->rightwork) {
2067bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr);
2077bf3a71bSJakub Kruzik     }
2087bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr);
2097bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
2107bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr);
2117bf3a71bSJakub Kruzik   }
2127bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
2137bf3a71bSJakub Kruzik }
2147bf3a71bSJakub Kruzik 
215793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
216793850ffSBarry Smith {
217793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
218793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
219793850ffSBarry Smith   PetscErrorCode    ierr;
220793850ffSBarry Smith 
221793850ffSBarry Smith   PetscFunctionBegin;
222e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
223e32f2f54SBarry Smith   if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling");
224e4fc5df0SBarry Smith 
225793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
226793850ffSBarry Smith   if (next->next && !shell->work) {
227793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
228793850ffSBarry Smith   }
229793850ffSBarry Smith   while ((next = next->next)) {
230793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
231793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
232793850ffSBarry Smith   }
233e4fc5df0SBarry Smith   ierr = VecScale(v,shell->scale);CHKERRQ(ierr);
234793850ffSBarry Smith   PetscFunctionReturn(0);
235793850ffSBarry Smith }
236793850ffSBarry Smith 
237793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
238793850ffSBarry Smith {
2394b2558d6SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)Y->data;
240b52f573bSBarry Smith   PetscErrorCode    ierr;
241b52f573bSBarry Smith 
242793850ffSBarry Smith   PetscFunctionBegin;
2434b2558d6SJakub Kruzik   if (shell->merge) {
244b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
245b52f573bSBarry Smith   }
246793850ffSBarry Smith   PetscFunctionReturn(0);
247793850ffSBarry Smith }
248793850ffSBarry Smith 
249e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha)
250e4fc5df0SBarry Smith {
251e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite*)inA->data;
252e4fc5df0SBarry Smith 
253e4fc5df0SBarry Smith   PetscFunctionBegin;
254321429dbSBarry Smith   a->scale *= alpha;
255e4fc5df0SBarry Smith   PetscFunctionReturn(0);
256e4fc5df0SBarry Smith }
257e4fc5df0SBarry Smith 
258e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right)
259e4fc5df0SBarry Smith {
260e4fc5df0SBarry Smith   Mat_Composite  *a = (Mat_Composite*)inA->data;
261e4fc5df0SBarry Smith   PetscErrorCode ierr;
262e4fc5df0SBarry Smith 
263e4fc5df0SBarry Smith   PetscFunctionBegin;
264e4fc5df0SBarry Smith   if (left) {
265321429dbSBarry Smith     if (!a->left) {
266e4fc5df0SBarry Smith       ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr);
267e4fc5df0SBarry Smith       ierr = VecCopy(left,a->left);CHKERRQ(ierr);
268321429dbSBarry Smith     } else {
269321429dbSBarry Smith       ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr);
270321429dbSBarry Smith     }
271e4fc5df0SBarry Smith   }
272e4fc5df0SBarry Smith   if (right) {
273321429dbSBarry Smith     if (!a->right) {
274e4fc5df0SBarry Smith       ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr);
275e4fc5df0SBarry Smith       ierr = VecCopy(right,a->right);CHKERRQ(ierr);
276321429dbSBarry Smith     } else {
277321429dbSBarry Smith       ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr);
278321429dbSBarry Smith     }
279e4fc5df0SBarry Smith   }
280e4fc5df0SBarry Smith   PetscFunctionReturn(0);
281e4fc5df0SBarry Smith }
282793850ffSBarry Smith 
2834b2558d6SJakub Kruzik PetscErrorCode MatSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,Mat A)
2844b2558d6SJakub Kruzik {
2854b2558d6SJakub Kruzik   Mat_Composite  *a = (Mat_Composite*)A->data;
2864b2558d6SJakub Kruzik   PetscErrorCode ierr;
2874b2558d6SJakub Kruzik 
2884b2558d6SJakub Kruzik   PetscFunctionBegin;
2894b2558d6SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"MATCOMPOSITE options");CHKERRQ(ierr);
2904b2558d6SJakub Kruzik   ierr = PetscOptionsBool("-mat_composite_merge","Merge at MatAssemblyEnd","MatCompositeMerge",a->merge,&a->merge,NULL);CHKERRQ(ierr);
2918c8613bfSJakub Kruzik   ierr = PetscOptionsEnum("-mat_composite_merge_type","Set composite merge direction","MatCompositeSetMergeType",MatCompositeMergeTypes,(PetscEnum)a->mergetype,(PetscEnum*)&a->mergetype,NULL);CHKERRQ(ierr);
2924b2558d6SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
2934b2558d6SJakub Kruzik   PetscFunctionReturn(0);
2944b2558d6SJakub Kruzik }
2954b2558d6SJakub Kruzik 
2962c0821f3SBarry Smith /*@
2978bd739bdSJakub Kruzik    MatCreateComposite - Creates a matrix as the sum or product of one or more matrices
298793850ffSBarry Smith 
299*d083f849SBarry Smith   Collective
300793850ffSBarry Smith 
301793850ffSBarry Smith    Input Parameters:
302793850ffSBarry Smith +  comm - MPI communicator
303793850ffSBarry Smith .  nmat - number of matrices to put in
304793850ffSBarry Smith -  mats - the matrices
305793850ffSBarry Smith 
306793850ffSBarry Smith    Output Parameter:
307db36af27SMatthew G. Knepley .  mat - the matrix
308793850ffSBarry Smith 
3094b2558d6SJakub Kruzik    Options Database Keys:
3104b2558d6SJakub Kruzik +  -mat_composite_merge - merge in MatAssemblyEnd()
311b28d0daaSJakub Kruzik -  -mat_composite_merge_type - set merge direction
3124b2558d6SJakub Kruzik 
313793850ffSBarry Smith    Level: advanced
314793850ffSBarry Smith 
315793850ffSBarry Smith    Notes:
316793850ffSBarry Smith      Alternative construction
317793850ffSBarry Smith $       MatCreate(comm,&mat);
318793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
319793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
320793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
321793850ffSBarry Smith $       ....
322793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
323b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
324b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
325793850ffSBarry Smith 
3266d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
3276d7c1e57SBarry Smith 
3286dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE
329793850ffSBarry Smith 
330793850ffSBarry Smith @*/
3317087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
332793850ffSBarry Smith {
333793850ffSBarry Smith   PetscErrorCode ierr;
334793850ffSBarry Smith   PetscInt       m,n,M,N,i;
335793850ffSBarry Smith 
336793850ffSBarry Smith   PetscFunctionBegin;
337e32f2f54SBarry Smith   if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
338f3f84630SBarry Smith   PetscValidPointer(mat,3);
339793850ffSBarry Smith 
340c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr);
341c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr);
342c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr);
343c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr);
344793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
345793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
346793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
347793850ffSBarry Smith   for (i=0; i<nmat; i++) {
348793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
349793850ffSBarry Smith   }
350b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
351b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
352793850ffSBarry Smith   PetscFunctionReturn(0);
353793850ffSBarry Smith }
354793850ffSBarry Smith 
355d7f81bf2SJakub Kruzik 
356d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat)
357d7f81bf2SJakub Kruzik {
358d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
359d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink,next = shell->head;
360d7f81bf2SJakub Kruzik   PetscErrorCode    ierr;
361d7f81bf2SJakub Kruzik 
362d7f81bf2SJakub Kruzik   PetscFunctionBegin;
363d7f81bf2SJakub Kruzik   ierr        = PetscNewLog(mat,&ilink);CHKERRQ(ierr);
364d7f81bf2SJakub Kruzik   ilink->next = 0;
365d7f81bf2SJakub Kruzik   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
366d7f81bf2SJakub Kruzik   ilink->mat  = smat;
367d7f81bf2SJakub Kruzik 
368d7f81bf2SJakub Kruzik   if (!next) shell->head = ilink;
369d7f81bf2SJakub Kruzik   else {
370d7f81bf2SJakub Kruzik     while (next->next) {
371d7f81bf2SJakub Kruzik       next = next->next;
372d7f81bf2SJakub Kruzik     }
373d7f81bf2SJakub Kruzik     next->next  = ilink;
374d7f81bf2SJakub Kruzik     ilink->prev = next;
375d7f81bf2SJakub Kruzik   }
376d7f81bf2SJakub Kruzik   shell->tail =  ilink;
377d7f81bf2SJakub Kruzik   shell->nmat += 1;
378d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
379d7f81bf2SJakub Kruzik }
380d7f81bf2SJakub Kruzik 
381793850ffSBarry Smith /*@
3828bd739bdSJakub Kruzik     MatCompositeAddMat - Add another matrix to a composite matrix.
383793850ffSBarry Smith 
384793850ffSBarry Smith    Collective on Mat
385793850ffSBarry Smith 
386793850ffSBarry Smith     Input Parameters:
387793850ffSBarry Smith +   mat - the composite matrix
388793850ffSBarry Smith -   smat - the partial matrix
389793850ffSBarry Smith 
390793850ffSBarry Smith    Level: advanced
391793850ffSBarry Smith 
3928bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
393793850ffSBarry Smith @*/
3947087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat)
395793850ffSBarry Smith {
396793850ffSBarry Smith   PetscErrorCode    ierr;
397793850ffSBarry Smith 
398793850ffSBarry Smith   PetscFunctionBegin;
3990700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4000700a824SBarry Smith   PetscValidHeaderSpecific(smat,MAT_CLASSID,2);
401d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr);
402d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
403d7f81bf2SJakub Kruzik }
404793850ffSBarry Smith 
405d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type)
406d7f81bf2SJakub Kruzik {
407d7f81bf2SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
408d7f81bf2SJakub Kruzik 
409d7f81bf2SJakub Kruzik   PetscFunctionBegin;
410ced1ac25SJakub Kruzik   b->type = type;
411d7f81bf2SJakub Kruzik   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
412d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = 0;
413d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite_Multiplicative;
414d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
415d7f81bf2SJakub Kruzik   } else {
416d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
417d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite;
418d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite;
419793850ffSBarry Smith   }
4206d7c1e57SBarry Smith   PetscFunctionReturn(0);
4216d7c1e57SBarry Smith }
4226d7c1e57SBarry Smith 
4232c0821f3SBarry Smith /*@
4248bd739bdSJakub Kruzik    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product.
4256d7c1e57SBarry Smith 
426b2b245abSJakub Kruzik    Logically Collective on Mat
4276d7c1e57SBarry Smith 
4286d7c1e57SBarry Smith    Input Parameters:
4296d7c1e57SBarry Smith .  mat - the composite matrix
4306d7c1e57SBarry Smith 
4316d7c1e57SBarry Smith    Level: advanced
4326d7c1e57SBarry Smith 
4336dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE
4346d7c1e57SBarry Smith 
4356d7c1e57SBarry Smith @*/
4367087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type)
4376d7c1e57SBarry Smith {
4386d7c1e57SBarry Smith   PetscErrorCode ierr;
4396d7c1e57SBarry Smith 
4406d7c1e57SBarry Smith   PetscFunctionBegin;
441d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
442b2b245abSJakub Kruzik   PetscValidLogicalCollectiveEnum(mat,type,2);
443d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr);
444793850ffSBarry Smith   PetscFunctionReturn(0);
445793850ffSBarry Smith }
446793850ffSBarry Smith 
4476dbc55e5SJakub Kruzik static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type)
4486dbc55e5SJakub Kruzik {
4496dbc55e5SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
4506dbc55e5SJakub Kruzik 
4516dbc55e5SJakub Kruzik   PetscFunctionBegin;
4526dbc55e5SJakub Kruzik   *type = b->type;
4536dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4546dbc55e5SJakub Kruzik }
4556dbc55e5SJakub Kruzik 
4566dbc55e5SJakub Kruzik /*@
4576dbc55e5SJakub Kruzik    MatCompositeGetType - Returns type of composite.
4586dbc55e5SJakub Kruzik 
4596dbc55e5SJakub Kruzik    Not Collective
4606dbc55e5SJakub Kruzik 
4616dbc55e5SJakub Kruzik    Input Parameter:
4626dbc55e5SJakub Kruzik .  mat - the composite matrix
4636dbc55e5SJakub Kruzik 
4646dbc55e5SJakub Kruzik    Output Parameter:
4656dbc55e5SJakub Kruzik .  type - type of composite
4666dbc55e5SJakub Kruzik 
4676dbc55e5SJakub Kruzik    Level: advanced
4686dbc55e5SJakub Kruzik 
4696dbc55e5SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE
4706dbc55e5SJakub Kruzik 
4716dbc55e5SJakub Kruzik @*/
4726dbc55e5SJakub Kruzik PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type)
4736dbc55e5SJakub Kruzik {
4746dbc55e5SJakub Kruzik   PetscErrorCode ierr;
4756dbc55e5SJakub Kruzik 
4766dbc55e5SJakub Kruzik   PetscFunctionBegin;
4776dbc55e5SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4786dbc55e5SJakub Kruzik   PetscValidPointer(type,2);
4796dbc55e5SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr);
4806dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4816dbc55e5SJakub Kruzik }
4826dbc55e5SJakub Kruzik 
4833b35acafSJakub Kruzik static PetscErrorCode MatCompositeSetMatStructure_Composite(Mat mat,MatStructure str)
4843b35acafSJakub Kruzik {
4853b35acafSJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
4863b35acafSJakub Kruzik 
4873b35acafSJakub Kruzik   PetscFunctionBegin;
4883b35acafSJakub Kruzik   b->structure = str;
4893b35acafSJakub Kruzik   PetscFunctionReturn(0);
4903b35acafSJakub Kruzik }
4913b35acafSJakub Kruzik 
4923b35acafSJakub Kruzik /*@
4933b35acafSJakub Kruzik    MatCompositeSetMatStructure - Indicates structure of matrices in the composite matrix.
4943b35acafSJakub Kruzik 
4953b35acafSJakub Kruzik    Not Collective
4963b35acafSJakub Kruzik 
4973b35acafSJakub Kruzik    Input Parameters:
4983b35acafSJakub Kruzik +  mat - the composite matrix
4993b35acafSJakub Kruzik -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN (default) or SUBSET_NONZERO_PATTERN
5003b35acafSJakub Kruzik 
5013b35acafSJakub Kruzik    Level: advanced
5023b35acafSJakub Kruzik 
5033b35acafSJakub Kruzik    Notes:
5043b35acafSJakub Kruzik     Information about the matrices structure is used in MatCompositeMerge() for additive composite matrix.
5053b35acafSJakub Kruzik 
5063b35acafSJakub Kruzik .seealso: MatAXPY(), MatCreateComposite(), MatCompositeMerge() MatCompositeGetMatStructure(), MATCOMPOSITE
5073b35acafSJakub Kruzik 
5083b35acafSJakub Kruzik @*/
5093b35acafSJakub Kruzik PetscErrorCode MatCompositeSetMatStructure(Mat mat,MatStructure str)
5103b35acafSJakub Kruzik {
5113b35acafSJakub Kruzik   PetscErrorCode ierr;
5123b35acafSJakub Kruzik 
5133b35acafSJakub Kruzik   PetscFunctionBegin;
5143b35acafSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5153b35acafSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetMatStructure_C",(Mat,MatStructure),(mat,str));CHKERRQ(ierr);
5163b35acafSJakub Kruzik   PetscFunctionReturn(0);
5173b35acafSJakub Kruzik }
5183b35acafSJakub Kruzik 
5193b35acafSJakub Kruzik static PetscErrorCode MatCompositeGetMatStructure_Composite(Mat mat,MatStructure *str)
5203b35acafSJakub Kruzik {
5213b35acafSJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
5223b35acafSJakub Kruzik 
5233b35acafSJakub Kruzik   PetscFunctionBegin;
5243b35acafSJakub Kruzik   *str = b->structure;
5253b35acafSJakub Kruzik   PetscFunctionReturn(0);
5263b35acafSJakub Kruzik }
5273b35acafSJakub Kruzik 
5283b35acafSJakub Kruzik /*@
5293b35acafSJakub Kruzik    MatCompositeGetMatStructure - Returns the structure of matrices in the composite matrix.
5303b35acafSJakub Kruzik 
5313b35acafSJakub Kruzik    Not Collective
5323b35acafSJakub Kruzik 
5333b35acafSJakub Kruzik    Input Parameter:
5343b35acafSJakub Kruzik .  mat - the composite matrix
5353b35acafSJakub Kruzik 
5363b35acafSJakub Kruzik    Output Parameter:
5373b35acafSJakub Kruzik .  str - structure of the matrices
5383b35acafSJakub Kruzik 
5393b35acafSJakub Kruzik    Level: advanced
5403b35acafSJakub Kruzik 
5413b35acafSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetMatStructure(), MATCOMPOSITE
5423b35acafSJakub Kruzik 
5433b35acafSJakub Kruzik @*/
5443b35acafSJakub Kruzik PetscErrorCode MatCompositeGetMatStructure(Mat mat,MatStructure *str)
5453b35acafSJakub Kruzik {
5463b35acafSJakub Kruzik   PetscErrorCode ierr;
5473b35acafSJakub Kruzik 
5483b35acafSJakub Kruzik   PetscFunctionBegin;
5493b35acafSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5503b35acafSJakub Kruzik   PetscValidPointer(str,2);
5513b35acafSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetMatStructure_C",(Mat,MatStructure*),(mat,str));CHKERRQ(ierr);
5523b35acafSJakub Kruzik   PetscFunctionReturn(0);
5533b35acafSJakub Kruzik }
5543b35acafSJakub Kruzik 
5558c8613bfSJakub Kruzik static PetscErrorCode MatCompositeSetMergeType_Composite(Mat mat,MatCompositeMergeType type)
5568c8613bfSJakub Kruzik {
5578c8613bfSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
5588c8613bfSJakub Kruzik 
5598c8613bfSJakub Kruzik   PetscFunctionBegin;
5608c8613bfSJakub Kruzik   shell->mergetype = type;
5618c8613bfSJakub Kruzik   PetscFunctionReturn(0);
5628c8613bfSJakub Kruzik }
5638c8613bfSJakub Kruzik 
5648c8613bfSJakub Kruzik /*@
5658c8613bfSJakub Kruzik    MatCompositeSetMergeType - Sets order of MatCompositeMerge().
5668c8613bfSJakub Kruzik 
5678c8613bfSJakub Kruzik    Logically Collective on Mat
5688c8613bfSJakub Kruzik 
5698c8613bfSJakub Kruzik    Input Parameter:
5708c8613bfSJakub Kruzik +  mat - the composite matrix
5718c8613bfSJakub Kruzik -  type - MAT_COMPOSITE_MERGE RIGHT (default) to start merge from right with the first added matrix (mat[0]),
5728c8613bfSJakub Kruzik           MAT_COMPOSITE_MERGE_LEFT to start merge from left with the last added matrix (mat[nmat-1])
5738c8613bfSJakub Kruzik 
5748c8613bfSJakub Kruzik    Level: advanced
5758c8613bfSJakub Kruzik 
5768c8613bfSJakub Kruzik    Notes:
5778c8613bfSJakub Kruzik     The resulting matrix is the same regardles of the MergeType. Only the order of operation is changed.
5788c8613bfSJakub Kruzik     If set to MAT_COMPOSITE_MERGE_RIGHT the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0])))
5798c8613bfSJakub Kruzik     otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0].
5808c8613bfSJakub Kruzik 
5818c8613bfSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE
5828c8613bfSJakub Kruzik 
5838c8613bfSJakub Kruzik @*/
5848c8613bfSJakub Kruzik PetscErrorCode MatCompositeSetMergeType(Mat mat,MatCompositeMergeType type)
5858c8613bfSJakub Kruzik {
5868c8613bfSJakub Kruzik   PetscErrorCode ierr;
5878c8613bfSJakub Kruzik 
5888c8613bfSJakub Kruzik   PetscFunctionBegin;
5898c8613bfSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5908c8613bfSJakub Kruzik   PetscValidLogicalCollectiveEnum(mat,type,2);
5918c8613bfSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetMergeType_C",(Mat,MatCompositeMergeType),(mat,type));CHKERRQ(ierr);
5928c8613bfSJakub Kruzik   PetscFunctionReturn(0);
5938c8613bfSJakub Kruzik }
5948c8613bfSJakub Kruzik 
595d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat)
596b52f573bSBarry Smith {
597b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
5986d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head, prev = shell->tail;
599b52f573bSBarry Smith   PetscErrorCode    ierr;
6006d7c1e57SBarry Smith   Mat               tmat,newmat;
6011ba60692SJed Brown   Vec               left,right;
6021ba60692SJed Brown   PetscScalar       scale;
603b52f573bSBarry Smith 
604b52f573bSBarry Smith   PetscFunctionBegin;
605e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
606b52f573bSBarry Smith 
607b52f573bSBarry Smith   PetscFunctionBegin;
6086d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
6098c8613bfSJakub Kruzik     if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) {
610b52f573bSBarry Smith       ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
611b52f573bSBarry Smith       while ((next = next->next)) {
6123b35acafSJakub Kruzik         ierr = MatAXPY(tmat,1.0,next->mat,shell->structure);CHKERRQ(ierr);
613b52f573bSBarry Smith       }
6146d7c1e57SBarry Smith     } else {
6158c8613bfSJakub Kruzik       ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6168c8613bfSJakub Kruzik       while ((prev = prev->prev)) {
6173b35acafSJakub Kruzik         ierr = MatAXPY(tmat,1.0,prev->mat,shell->structure);CHKERRQ(ierr);
6188c8613bfSJakub Kruzik       }
6198c8613bfSJakub Kruzik     }
6208c8613bfSJakub Kruzik   } else {
6218c8613bfSJakub Kruzik     if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) {
6226d7c1e57SBarry Smith       ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
623b6cfcaf5SJakub Kruzik       while ((next = next->next)) {
624b6cfcaf5SJakub Kruzik         ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
6256bf464f9SBarry Smith         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6266d7c1e57SBarry Smith         tmat = newmat;
6276d7c1e57SBarry Smith       }
62804d534ceSJakub Kruzik     } else {
62904d534ceSJakub Kruzik       ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
63004d534ceSJakub Kruzik       while ((prev = prev->prev)) {
63104d534ceSJakub Kruzik         ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
63204d534ceSJakub Kruzik         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
63304d534ceSJakub Kruzik         tmat = newmat;
63404d534ceSJakub Kruzik       }
63504d534ceSJakub Kruzik     }
6366d7c1e57SBarry Smith   }
6371ba60692SJed Brown 
6381ba60692SJed Brown   scale = shell->scale;
6391ba60692SJed Brown   if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);}
6401ba60692SJed Brown   if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);}
6411ba60692SJed Brown 
64228be2f97SBarry Smith   ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr);
6431ba60692SJed Brown 
6441ba60692SJed Brown   ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr);
6451ba60692SJed Brown   ierr = MatScale(mat,scale);CHKERRQ(ierr);
6461ba60692SJed Brown   ierr = VecDestroy(&left);CHKERRQ(ierr);
6471ba60692SJed Brown   ierr = VecDestroy(&right);CHKERRQ(ierr);
648b52f573bSBarry Smith   PetscFunctionReturn(0);
649b52f573bSBarry Smith }
6506a7ede75SJakub Kruzik 
6516a7ede75SJakub Kruzik /*@
652d7f81bf2SJakub Kruzik    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
6538bd739bdSJakub Kruzik      by summing or computing the product of all the matrices inside the composite matrix.
654d7f81bf2SJakub Kruzik 
655b2b245abSJakub Kruzik   Collective
656d7f81bf2SJakub Kruzik 
657d7f81bf2SJakub Kruzik    Input Parameters:
658d7f81bf2SJakub Kruzik .  mat - the composite matrix
659d7f81bf2SJakub Kruzik 
660d7f81bf2SJakub Kruzik 
6614b2558d6SJakub Kruzik    Options Database Keys:
662b28d0daaSJakub Kruzik +  -mat_composite_merge - merge in MatAssemblyEnd()
663b28d0daaSJakub Kruzik -  -mat_composite_merge_type - set merge direction
664d7f81bf2SJakub Kruzik 
665d7f81bf2SJakub Kruzik    Level: advanced
666d7f81bf2SJakub Kruzik 
667d7f81bf2SJakub Kruzik    Notes:
668d7f81bf2SJakub Kruzik       The MatType of the resulting matrix will be the same as the MatType of the FIRST
669d7f81bf2SJakub Kruzik     matrix in the composite matrix.
670d7f81bf2SJakub Kruzik 
6713b35acafSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMatStructure(), MatCompositeSetMergeType(), MATCOMPOSITE
672d7f81bf2SJakub Kruzik 
673d7f81bf2SJakub Kruzik @*/
674d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat)
675d7f81bf2SJakub Kruzik {
676d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
677d7f81bf2SJakub Kruzik 
678d7f81bf2SJakub Kruzik   PetscFunctionBegin;
679d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
680d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr);
681d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
682d7f81bf2SJakub Kruzik }
683d7f81bf2SJakub Kruzik 
6846d0add67SJakub Kruzik static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat,PetscInt *nmat)
685d7f81bf2SJakub Kruzik {
686d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
687d7f81bf2SJakub Kruzik 
688d7f81bf2SJakub Kruzik   PetscFunctionBegin;
689d7f81bf2SJakub Kruzik   *nmat = shell->nmat;
690d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
691d7f81bf2SJakub Kruzik }
692d7f81bf2SJakub Kruzik 
693d7f81bf2SJakub Kruzik /*@
6946d0add67SJakub Kruzik    MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix.
6956a7ede75SJakub Kruzik 
6966a7ede75SJakub Kruzik    Not Collective
6976a7ede75SJakub Kruzik 
6986a7ede75SJakub Kruzik    Input Parameter:
699d7f81bf2SJakub Kruzik .  mat - the composite matrix
7006a7ede75SJakub Kruzik 
7016a7ede75SJakub Kruzik    Output Parameter:
7026d0add67SJakub Kruzik .  nmat - number of matrices in the composite matrix
7036a7ede75SJakub Kruzik 
7048b5c3584SJakub Kruzik    Level: advanced
7056a7ede75SJakub Kruzik 
7068bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
7076a7ede75SJakub Kruzik 
7086a7ede75SJakub Kruzik @*/
7096d0add67SJakub Kruzik PetscErrorCode MatCompositeGetNumberMat(Mat mat,PetscInt *nmat)
7106a7ede75SJakub Kruzik {
711d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
7126a7ede75SJakub Kruzik 
7136a7ede75SJakub Kruzik   PetscFunctionBegin;
714d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7156a7ede75SJakub Kruzik   PetscValidPointer(nmat,2);
7166d0add67SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetNumberMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr);
717d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
718d7f81bf2SJakub Kruzik }
719d7f81bf2SJakub Kruzik 
720d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai)
721d7f81bf2SJakub Kruzik {
722d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
723d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink;
724d7f81bf2SJakub Kruzik   PetscInt          k;
725d7f81bf2SJakub Kruzik 
726d7f81bf2SJakub Kruzik   PetscFunctionBegin;
727d7f81bf2SJakub Kruzik   if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat);
728d7f81bf2SJakub Kruzik   ilink = shell->head;
729d7f81bf2SJakub Kruzik   for (k=0; k<i; k++) {
730d7f81bf2SJakub Kruzik     ilink = ilink->next;
731d7f81bf2SJakub Kruzik   }
732d7f81bf2SJakub Kruzik   *Ai = ilink->mat;
7336a7ede75SJakub Kruzik   PetscFunctionReturn(0);
7346a7ede75SJakub Kruzik }
7356a7ede75SJakub Kruzik 
7368b5c3584SJakub Kruzik /*@
7378bd739bdSJakub Kruzik    MatCompositeGetMat - Returns the ith matrix from the composite matrix.
7388b5c3584SJakub Kruzik 
7398b5c3584SJakub Kruzik    Logically Collective on Mat
7408b5c3584SJakub Kruzik 
7418b5c3584SJakub Kruzik    Input Parameter:
742d7f81bf2SJakub Kruzik +  mat - the composite matrix
7438b5c3584SJakub Kruzik -  i - the number of requested matrix
7448b5c3584SJakub Kruzik 
7458b5c3584SJakub Kruzik    Output Parameter:
7468b5c3584SJakub Kruzik .  Ai - ith matrix in composite
7478b5c3584SJakub Kruzik 
7488b5c3584SJakub Kruzik    Level: advanced
7498b5c3584SJakub Kruzik 
7506d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNumberMat(), MatCompositeAddMat(), MATCOMPOSITE
7518b5c3584SJakub Kruzik 
7528b5c3584SJakub Kruzik @*/
753d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai)
7548b5c3584SJakub Kruzik {
755d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
7568b5c3584SJakub Kruzik 
7578b5c3584SJakub Kruzik   PetscFunctionBegin;
758d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
759d7f81bf2SJakub Kruzik   PetscValidLogicalCollectiveInt(mat,i,2);
7608b5c3584SJakub Kruzik   PetscValidPointer(Ai,3);
761d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr);
7628b5c3584SJakub Kruzik   PetscFunctionReturn(0);
7638b5c3584SJakub Kruzik }
7648b5c3584SJakub Kruzik 
76541cd0125SJakub Kruzik static struct _MatOps MatOps_Values = {0,
76641cd0125SJakub Kruzik                                        0,
76741cd0125SJakub Kruzik                                        0,
76841cd0125SJakub Kruzik                                        MatMult_Composite,
7697bf3a71bSJakub Kruzik                                        MatMultAdd_Composite,
77041cd0125SJakub Kruzik                                 /*  5*/ MatMultTranspose_Composite,
7717bf3a71bSJakub Kruzik                                        MatMultTransposeAdd_Composite,
77241cd0125SJakub Kruzik                                        0,
77341cd0125SJakub Kruzik                                        0,
77441cd0125SJakub Kruzik                                        0,
77541cd0125SJakub Kruzik                                 /* 10*/ 0,
77641cd0125SJakub Kruzik                                        0,
77741cd0125SJakub Kruzik                                        0,
77841cd0125SJakub Kruzik                                        0,
77941cd0125SJakub Kruzik                                        0,
78041cd0125SJakub Kruzik                                 /* 15*/ 0,
78141cd0125SJakub Kruzik                                        0,
78241cd0125SJakub Kruzik                                        MatGetDiagonal_Composite,
78341cd0125SJakub Kruzik                                        MatDiagonalScale_Composite,
78441cd0125SJakub Kruzik                                        0,
78541cd0125SJakub Kruzik                                 /* 20*/ 0,
78641cd0125SJakub Kruzik                                        MatAssemblyEnd_Composite,
78741cd0125SJakub Kruzik                                        0,
78841cd0125SJakub Kruzik                                        0,
78941cd0125SJakub Kruzik                                /* 24*/ 0,
79041cd0125SJakub Kruzik                                        0,
79141cd0125SJakub Kruzik                                        0,
79241cd0125SJakub Kruzik                                        0,
79341cd0125SJakub Kruzik                                        0,
79441cd0125SJakub Kruzik                                /* 29*/ 0,
79541cd0125SJakub Kruzik                                        0,
79641cd0125SJakub Kruzik                                        0,
79741cd0125SJakub Kruzik                                        0,
79841cd0125SJakub Kruzik                                        0,
79941cd0125SJakub Kruzik                                /* 34*/ 0,
80041cd0125SJakub Kruzik                                        0,
80141cd0125SJakub Kruzik                                        0,
80241cd0125SJakub Kruzik                                        0,
80341cd0125SJakub Kruzik                                        0,
80441cd0125SJakub Kruzik                                /* 39*/ 0,
80541cd0125SJakub Kruzik                                        0,
80641cd0125SJakub Kruzik                                        0,
80741cd0125SJakub Kruzik                                        0,
80841cd0125SJakub Kruzik                                        0,
80941cd0125SJakub Kruzik                                /* 44*/ 0,
81041cd0125SJakub Kruzik                                        MatScale_Composite,
81141cd0125SJakub Kruzik                                        MatShift_Basic,
81241cd0125SJakub Kruzik                                        0,
81341cd0125SJakub Kruzik                                        0,
81441cd0125SJakub Kruzik                                /* 49*/ 0,
81541cd0125SJakub Kruzik                                        0,
81641cd0125SJakub Kruzik                                        0,
81741cd0125SJakub Kruzik                                        0,
81841cd0125SJakub Kruzik                                        0,
81941cd0125SJakub Kruzik                                /* 54*/ 0,
82041cd0125SJakub Kruzik                                        0,
82141cd0125SJakub Kruzik                                        0,
82241cd0125SJakub Kruzik                                        0,
82341cd0125SJakub Kruzik                                        0,
82441cd0125SJakub Kruzik                                /* 59*/ 0,
82541cd0125SJakub Kruzik                                        MatDestroy_Composite,
82641cd0125SJakub Kruzik                                        0,
82741cd0125SJakub Kruzik                                        0,
82841cd0125SJakub Kruzik                                        0,
82941cd0125SJakub Kruzik                                /* 64*/ 0,
83041cd0125SJakub Kruzik                                        0,
83141cd0125SJakub Kruzik                                        0,
83241cd0125SJakub Kruzik                                        0,
83341cd0125SJakub Kruzik                                        0,
83441cd0125SJakub Kruzik                                /* 69*/ 0,
83541cd0125SJakub Kruzik                                        0,
83641cd0125SJakub Kruzik                                        0,
83741cd0125SJakub Kruzik                                        0,
83841cd0125SJakub Kruzik                                        0,
83941cd0125SJakub Kruzik                                /* 74*/ 0,
84041cd0125SJakub Kruzik                                        0,
8414b2558d6SJakub Kruzik                                        MatSetFromOptions_Composite,
84241cd0125SJakub Kruzik                                        0,
84341cd0125SJakub Kruzik                                        0,
84441cd0125SJakub Kruzik                                /* 79*/ 0,
84541cd0125SJakub Kruzik                                        0,
84641cd0125SJakub Kruzik                                        0,
84741cd0125SJakub Kruzik                                        0,
84841cd0125SJakub Kruzik                                        0,
84941cd0125SJakub Kruzik                                /* 84*/ 0,
85041cd0125SJakub Kruzik                                        0,
85141cd0125SJakub Kruzik                                        0,
85241cd0125SJakub Kruzik                                        0,
85341cd0125SJakub Kruzik                                        0,
85441cd0125SJakub Kruzik                                /* 89*/ 0,
85541cd0125SJakub Kruzik                                        0,
85641cd0125SJakub Kruzik                                        0,
85741cd0125SJakub Kruzik                                        0,
85841cd0125SJakub Kruzik                                        0,
85941cd0125SJakub Kruzik                                /* 94*/ 0,
86041cd0125SJakub Kruzik                                        0,
86141cd0125SJakub Kruzik                                        0,
86241cd0125SJakub Kruzik                                        0,
86341cd0125SJakub Kruzik                                        0,
86441cd0125SJakub Kruzik                                 /*99*/ 0,
86541cd0125SJakub Kruzik                                        0,
86641cd0125SJakub Kruzik                                        0,
86741cd0125SJakub Kruzik                                        0,
86841cd0125SJakub Kruzik                                        0,
86941cd0125SJakub Kruzik                                /*104*/ 0,
87041cd0125SJakub Kruzik                                        0,
87141cd0125SJakub Kruzik                                        0,
87241cd0125SJakub Kruzik                                        0,
87341cd0125SJakub Kruzik                                        0,
87441cd0125SJakub Kruzik                                /*109*/ 0,
87541cd0125SJakub Kruzik                                        0,
87641cd0125SJakub Kruzik                                        0,
87741cd0125SJakub Kruzik                                        0,
87841cd0125SJakub Kruzik                                        0,
87941cd0125SJakub Kruzik                                /*114*/ 0,
88041cd0125SJakub Kruzik                                        0,
88141cd0125SJakub Kruzik                                        0,
88241cd0125SJakub Kruzik                                        0,
88341cd0125SJakub Kruzik                                        0,
88441cd0125SJakub Kruzik                                /*119*/ 0,
88541cd0125SJakub Kruzik                                        0,
88641cd0125SJakub Kruzik                                        0,
88741cd0125SJakub Kruzik                                        0,
88841cd0125SJakub Kruzik                                        0,
88941cd0125SJakub Kruzik                                /*124*/ 0,
89041cd0125SJakub Kruzik                                        0,
89141cd0125SJakub Kruzik                                        0,
89241cd0125SJakub Kruzik                                        0,
89341cd0125SJakub Kruzik                                        0,
89441cd0125SJakub Kruzik                                /*129*/ 0,
89541cd0125SJakub Kruzik                                        0,
89641cd0125SJakub Kruzik                                        0,
89741cd0125SJakub Kruzik                                        0,
89841cd0125SJakub Kruzik                                        0,
89941cd0125SJakub Kruzik                                /*134*/ 0,
90041cd0125SJakub Kruzik                                        0,
90141cd0125SJakub Kruzik                                        0,
90241cd0125SJakub Kruzik                                        0,
90341cd0125SJakub Kruzik                                        0,
90441cd0125SJakub Kruzik                                /*139*/ 0,
90541cd0125SJakub Kruzik                                        0,
90641cd0125SJakub Kruzik                                        0
90741cd0125SJakub Kruzik };
90841cd0125SJakub Kruzik 
90941cd0125SJakub Kruzik /*MC
91041cd0125SJakub Kruzik    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices.
91141cd0125SJakub Kruzik     The matrices need to have a correct size and parallel layout for the sum or product to be valid.
91241cd0125SJakub Kruzik 
91341cd0125SJakub Kruzik    Notes:
91441cd0125SJakub Kruzik     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
91541cd0125SJakub Kruzik 
91641cd0125SJakub Kruzik   Level: advanced
91741cd0125SJakub Kruzik 
918de0460efSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeSetMatStructure(), MatCompositeGetMatStructure(), MatCompositeMerge(), MatCompositeSetMergeType(), MatCompositeGetNumberMat(), MatCompositeGetMat()
91941cd0125SJakub Kruzik M*/
92041cd0125SJakub Kruzik 
92141cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A)
92241cd0125SJakub Kruzik {
92341cd0125SJakub Kruzik   Mat_Composite  *b;
92441cd0125SJakub Kruzik   PetscErrorCode ierr;
92541cd0125SJakub Kruzik 
92641cd0125SJakub Kruzik   PetscFunctionBegin;
92741cd0125SJakub Kruzik   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
92841cd0125SJakub Kruzik   A->data = (void*)b;
92941cd0125SJakub Kruzik   ierr    = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
93041cd0125SJakub Kruzik 
93141cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
93241cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
93341cd0125SJakub Kruzik 
93441cd0125SJakub Kruzik   A->assembled    = PETSC_TRUE;
93541cd0125SJakub Kruzik   A->preallocated = PETSC_TRUE;
93641cd0125SJakub Kruzik   b->type         = MAT_COMPOSITE_ADDITIVE;
93741cd0125SJakub Kruzik   b->scale        = 1.0;
93841cd0125SJakub Kruzik   b->nmat         = 0;
9394b2558d6SJakub Kruzik   b->merge        = PETSC_FALSE;
9408c8613bfSJakub Kruzik   b->mergetype    = MAT_COMPOSITE_MERGE_RIGHT;
9413b35acafSJakub Kruzik   b->structure    = DIFFERENT_NONZERO_PATTERN;
94241cd0125SJakub Kruzik 
94341cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr);
94441cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr);
9456dbc55e5SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr);
9468c8613bfSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeType_C",MatCompositeSetMergeType_Composite);CHKERRQ(ierr);
9473b35acafSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMatStructure_C",MatCompositeSetMatStructure_Composite);CHKERRQ(ierr);
9483b35acafSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMatStructure_C",MatCompositeGetMatStructure_Composite);CHKERRQ(ierr);
94941cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr);
9506d0add67SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNumberMat_C",MatCompositeGetNumberMat_Composite);CHKERRQ(ierr);
95141cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr);
95241cd0125SJakub Kruzik 
95341cd0125SJakub Kruzik   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
95441cd0125SJakub Kruzik   PetscFunctionReturn(0);
95541cd0125SJakub Kruzik }
95641cd0125SJakub Kruzik 
957