xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 6d0add670cfef625b859aef85345153aa47788d0)
1793850ffSBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
3793850ffSBarry Smith 
4793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink;
5793850ffSBarry Smith struct _Mat_CompositeLink {
6793850ffSBarry Smith   Mat               mat;
76d7c1e57SBarry Smith   Vec               work;
86d7c1e57SBarry Smith   Mat_CompositeLink next,prev;
9793850ffSBarry Smith };
10793850ffSBarry Smith 
11793850ffSBarry Smith typedef struct {
126d7c1e57SBarry Smith   MatCompositeType  type;
136d7c1e57SBarry Smith   Mat_CompositeLink head,tail;
14793850ffSBarry Smith   Vec               work;
15e4fc5df0SBarry Smith   PetscScalar       scale;        /* scale factor supplied with MatScale() */
16e4fc5df0SBarry Smith   Vec               left,right;   /* left and right diagonal scaling provided with MatDiagonalScale() */
17e4fc5df0SBarry Smith   Vec               leftwork,rightwork;
186a7ede75SJakub Kruzik   PetscInt          nmat;
1904d534ceSJakub Kruzik   PetscBool         mergefromright;
20793850ffSBarry Smith } Mat_Composite;
21793850ffSBarry Smith 
22793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
23793850ffSBarry Smith {
24793850ffSBarry Smith   PetscErrorCode    ierr;
252c33bbaeSSatish Balay   Mat_Composite     *shell = (Mat_Composite*)mat->data;
266d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head,oldnext;
27793850ffSBarry Smith 
28793850ffSBarry Smith   PetscFunctionBegin;
29793850ffSBarry Smith   while (next) {
306bf464f9SBarry Smith     ierr = MatDestroy(&next->mat);CHKERRQ(ierr);
316d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
326bf464f9SBarry Smith       ierr = VecDestroy(&next->work);CHKERRQ(ierr);
336d7c1e57SBarry Smith     }
346d7c1e57SBarry Smith     oldnext = next;
35793850ffSBarry Smith     next    = next->next;
366d7c1e57SBarry Smith     ierr    = PetscFree(oldnext);CHKERRQ(ierr);
37793850ffSBarry Smith   }
386bf464f9SBarry Smith   ierr = VecDestroy(&shell->work);CHKERRQ(ierr);
396bf464f9SBarry Smith   ierr = VecDestroy(&shell->left);CHKERRQ(ierr);
406bf464f9SBarry Smith   ierr = VecDestroy(&shell->right);CHKERRQ(ierr);
416bf464f9SBarry Smith   ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr);
426bf464f9SBarry Smith   ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr);
436bf464f9SBarry Smith   ierr = PetscFree(mat->data);CHKERRQ(ierr);
44793850ffSBarry Smith   PetscFunctionReturn(0);
45793850ffSBarry Smith }
46793850ffSBarry Smith 
476d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
486d7c1e57SBarry Smith {
496d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
506d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head;
516d7c1e57SBarry Smith   PetscErrorCode    ierr;
526d7c1e57SBarry Smith   Vec               in,out;
536d7c1e57SBarry Smith 
546d7c1e57SBarry Smith   PetscFunctionBegin;
55e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
566d7c1e57SBarry Smith   in = x;
57e4fc5df0SBarry Smith   if (shell->right) {
58e4fc5df0SBarry Smith     if (!shell->rightwork) {
59e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
60e4fc5df0SBarry Smith     }
61e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
62e4fc5df0SBarry Smith     in   = shell->rightwork;
63e4fc5df0SBarry Smith   }
646d7c1e57SBarry Smith   while (next->next) {
656d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
662a7a6963SBarry Smith       ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr);
676d7c1e57SBarry Smith     }
686d7c1e57SBarry Smith     out  = next->work;
696d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
706d7c1e57SBarry Smith     in   = out;
716d7c1e57SBarry Smith     next = next->next;
726d7c1e57SBarry Smith   }
736d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
74e4fc5df0SBarry Smith   if (shell->left) {
75e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
76e4fc5df0SBarry Smith   }
77e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
786d7c1e57SBarry Smith   PetscFunctionReturn(0);
796d7c1e57SBarry Smith }
806d7c1e57SBarry Smith 
816d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
826d7c1e57SBarry Smith {
836d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
846d7c1e57SBarry Smith   Mat_CompositeLink tail   = shell->tail;
856d7c1e57SBarry Smith   PetscErrorCode    ierr;
866d7c1e57SBarry Smith   Vec               in,out;
876d7c1e57SBarry Smith 
886d7c1e57SBarry Smith   PetscFunctionBegin;
89e32f2f54SBarry Smith   if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
906d7c1e57SBarry Smith   in = x;
91e4fc5df0SBarry Smith   if (shell->left) {
92e4fc5df0SBarry Smith     if (!shell->leftwork) {
93e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
94e4fc5df0SBarry Smith     }
95e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
96e4fc5df0SBarry Smith     in   = shell->leftwork;
97e4fc5df0SBarry Smith   }
986d7c1e57SBarry Smith   while (tail->prev) {
996d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
1002a7a6963SBarry Smith       ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr);
1016d7c1e57SBarry Smith     }
1026d7c1e57SBarry Smith     out  = tail->prev->work;
1036d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
1046d7c1e57SBarry Smith     in   = out;
1056d7c1e57SBarry Smith     tail = tail->prev;
1066d7c1e57SBarry Smith   }
1076d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
108e4fc5df0SBarry Smith   if (shell->right) {
109e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
110e4fc5df0SBarry Smith   }
111e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
1126d7c1e57SBarry Smith   PetscFunctionReturn(0);
1136d7c1e57SBarry Smith }
1146d7c1e57SBarry Smith 
115793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
116793850ffSBarry Smith {
117793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
118793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
119793850ffSBarry Smith   PetscErrorCode    ierr;
120e4fc5df0SBarry Smith   Vec               in;
121793850ffSBarry Smith 
122793850ffSBarry Smith   PetscFunctionBegin;
123e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
124e4fc5df0SBarry Smith   in = x;
125e4fc5df0SBarry Smith   if (shell->right) {
126e4fc5df0SBarry Smith     if (!shell->rightwork) {
127e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
128793850ffSBarry Smith     }
129e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
130e4fc5df0SBarry Smith     in   = shell->rightwork;
131e4fc5df0SBarry Smith   }
132e4fc5df0SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
133e4fc5df0SBarry Smith   while ((next = next->next)) {
134e4fc5df0SBarry Smith     ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr);
135e4fc5df0SBarry Smith   }
136e4fc5df0SBarry Smith   if (shell->left) {
137e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
138e4fc5df0SBarry Smith   }
139e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
140793850ffSBarry Smith   PetscFunctionReturn(0);
141793850ffSBarry Smith }
142793850ffSBarry Smith 
143793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
144793850ffSBarry Smith {
145793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
146793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
147793850ffSBarry Smith   PetscErrorCode    ierr;
148e4fc5df0SBarry Smith   Vec               in;
149793850ffSBarry Smith 
150793850ffSBarry Smith   PetscFunctionBegin;
151e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
152e4fc5df0SBarry Smith   in = x;
153e4fc5df0SBarry Smith   if (shell->left) {
154e4fc5df0SBarry Smith     if (!shell->leftwork) {
155e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
156793850ffSBarry Smith     }
157e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
158e4fc5df0SBarry Smith     in   = shell->leftwork;
159e4fc5df0SBarry Smith   }
160e4fc5df0SBarry Smith   ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr);
161e4fc5df0SBarry Smith   while ((next = next->next)) {
162e4fc5df0SBarry Smith     ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr);
163e4fc5df0SBarry Smith   }
164e4fc5df0SBarry Smith   if (shell->right) {
165e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
166e4fc5df0SBarry Smith   }
167e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
168793850ffSBarry Smith   PetscFunctionReturn(0);
169793850ffSBarry Smith }
170793850ffSBarry Smith 
1717bf3a71bSJakub Kruzik PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z)
1727bf3a71bSJakub Kruzik {
1737bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1747bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1757bf3a71bSJakub Kruzik 
1767bf3a71bSJakub Kruzik   PetscFunctionBegin;
1777bf3a71bSJakub Kruzik   if (y != z) {
1787bf3a71bSJakub Kruzik     ierr = MatMult(A,x,z);CHKERRQ(ierr);
1797bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
1807bf3a71bSJakub Kruzik   } else {
1817bf3a71bSJakub Kruzik     if (!shell->leftwork) {
1827bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr);
1837bf3a71bSJakub Kruzik     }
1847bf3a71bSJakub Kruzik     ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr);
1857bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
1867bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr);
1877bf3a71bSJakub Kruzik   }
1887bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
1897bf3a71bSJakub Kruzik }
1907bf3a71bSJakub Kruzik 
1917bf3a71bSJakub Kruzik PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z)
1927bf3a71bSJakub Kruzik {
1937bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1947bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1957bf3a71bSJakub Kruzik 
1967bf3a71bSJakub Kruzik   PetscFunctionBegin;
1977bf3a71bSJakub Kruzik   if (y != z) {
1987bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr);
1997bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
2007bf3a71bSJakub Kruzik   } else {
2017bf3a71bSJakub Kruzik     if (!shell->rightwork) {
2027bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr);
2037bf3a71bSJakub Kruzik     }
2047bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr);
2057bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
2067bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr);
2077bf3a71bSJakub Kruzik   }
2087bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
2097bf3a71bSJakub Kruzik }
2107bf3a71bSJakub Kruzik 
211793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
212793850ffSBarry Smith {
213793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
214793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
215793850ffSBarry Smith   PetscErrorCode    ierr;
216793850ffSBarry Smith 
217793850ffSBarry Smith   PetscFunctionBegin;
218e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
219e32f2f54SBarry Smith   if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling");
220e4fc5df0SBarry Smith 
221793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
222793850ffSBarry Smith   if (next->next && !shell->work) {
223793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
224793850ffSBarry Smith   }
225793850ffSBarry Smith   while ((next = next->next)) {
226793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
227793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
228793850ffSBarry Smith   }
229e4fc5df0SBarry Smith   ierr = VecScale(v,shell->scale);CHKERRQ(ierr);
230793850ffSBarry Smith   PetscFunctionReturn(0);
231793850ffSBarry Smith }
232793850ffSBarry Smith 
233793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
234793850ffSBarry Smith {
235b52f573bSBarry Smith   PetscErrorCode ierr;
236ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
237b52f573bSBarry Smith 
238793850ffSBarry Smith   PetscFunctionBegin;
239c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)Y)->options,((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr);
240b52f573bSBarry Smith   if (flg) {
241b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
242b52f573bSBarry Smith   }
243793850ffSBarry Smith   PetscFunctionReturn(0);
244793850ffSBarry Smith }
245793850ffSBarry Smith 
246e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha)
247e4fc5df0SBarry Smith {
248e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite*)inA->data;
249e4fc5df0SBarry Smith 
250e4fc5df0SBarry Smith   PetscFunctionBegin;
251321429dbSBarry Smith   a->scale *= alpha;
252e4fc5df0SBarry Smith   PetscFunctionReturn(0);
253e4fc5df0SBarry Smith }
254e4fc5df0SBarry Smith 
255e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right)
256e4fc5df0SBarry Smith {
257e4fc5df0SBarry Smith   Mat_Composite  *a = (Mat_Composite*)inA->data;
258e4fc5df0SBarry Smith   PetscErrorCode ierr;
259e4fc5df0SBarry Smith 
260e4fc5df0SBarry Smith   PetscFunctionBegin;
261e4fc5df0SBarry Smith   if (left) {
262321429dbSBarry Smith     if (!a->left) {
263e4fc5df0SBarry Smith       ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr);
264e4fc5df0SBarry Smith       ierr = VecCopy(left,a->left);CHKERRQ(ierr);
265321429dbSBarry Smith     } else {
266321429dbSBarry Smith       ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr);
267321429dbSBarry Smith     }
268e4fc5df0SBarry Smith   }
269e4fc5df0SBarry Smith   if (right) {
270321429dbSBarry Smith     if (!a->right) {
271e4fc5df0SBarry Smith       ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr);
272e4fc5df0SBarry Smith       ierr = VecCopy(right,a->right);CHKERRQ(ierr);
273321429dbSBarry Smith     } else {
274321429dbSBarry Smith       ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr);
275321429dbSBarry Smith     }
276e4fc5df0SBarry Smith   }
277e4fc5df0SBarry Smith   PetscFunctionReturn(0);
278e4fc5df0SBarry Smith }
279793850ffSBarry Smith 
2802c0821f3SBarry Smith /*@
2818bd739bdSJakub Kruzik    MatCreateComposite - Creates a matrix as the sum or product of one or more matrices
282793850ffSBarry Smith 
283793850ffSBarry Smith   Collective on MPI_Comm
284793850ffSBarry Smith 
285793850ffSBarry Smith    Input Parameters:
286793850ffSBarry Smith +  comm - MPI communicator
287793850ffSBarry Smith .  nmat - number of matrices to put in
288793850ffSBarry Smith -  mats - the matrices
289793850ffSBarry Smith 
290793850ffSBarry Smith    Output Parameter:
291db36af27SMatthew G. Knepley .  mat - the matrix
292793850ffSBarry Smith 
293793850ffSBarry Smith    Level: advanced
294793850ffSBarry Smith 
295793850ffSBarry Smith    Notes:
296793850ffSBarry Smith      Alternative construction
297793850ffSBarry Smith $       MatCreate(comm,&mat);
298793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
299793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
300793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
301793850ffSBarry Smith $       ....
302793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
303b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
304b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
305793850ffSBarry Smith 
3066d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
3076d7c1e57SBarry Smith 
3086dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE
309793850ffSBarry Smith 
310793850ffSBarry Smith @*/
3117087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
312793850ffSBarry Smith {
313793850ffSBarry Smith   PetscErrorCode ierr;
314793850ffSBarry Smith   PetscInt       m,n,M,N,i;
315793850ffSBarry Smith 
316793850ffSBarry Smith   PetscFunctionBegin;
317e32f2f54SBarry Smith   if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
318f3f84630SBarry Smith   PetscValidPointer(mat,3);
319793850ffSBarry Smith 
320c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr);
321c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr);
322c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr);
323c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr);
324793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
325793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
326793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
327793850ffSBarry Smith   for (i=0; i<nmat; i++) {
328793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
329793850ffSBarry Smith   }
330b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
331b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
332793850ffSBarry Smith   PetscFunctionReturn(0);
333793850ffSBarry Smith }
334793850ffSBarry Smith 
335d7f81bf2SJakub Kruzik 
336d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat)
337d7f81bf2SJakub Kruzik {
338d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
339d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink,next = shell->head;
340d7f81bf2SJakub Kruzik   PetscErrorCode    ierr;
341d7f81bf2SJakub Kruzik 
342d7f81bf2SJakub Kruzik   PetscFunctionBegin;
343d7f81bf2SJakub Kruzik   ierr        = PetscNewLog(mat,&ilink);CHKERRQ(ierr);
344d7f81bf2SJakub Kruzik   ilink->next = 0;
345d7f81bf2SJakub Kruzik   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
346d7f81bf2SJakub Kruzik   ilink->mat  = smat;
347d7f81bf2SJakub Kruzik 
348d7f81bf2SJakub Kruzik   if (!next) shell->head = ilink;
349d7f81bf2SJakub Kruzik   else {
350d7f81bf2SJakub Kruzik     while (next->next) {
351d7f81bf2SJakub Kruzik       next = next->next;
352d7f81bf2SJakub Kruzik     }
353d7f81bf2SJakub Kruzik     next->next  = ilink;
354d7f81bf2SJakub Kruzik     ilink->prev = next;
355d7f81bf2SJakub Kruzik   }
356d7f81bf2SJakub Kruzik   shell->tail =  ilink;
357d7f81bf2SJakub Kruzik   shell->nmat += 1;
358d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
359d7f81bf2SJakub Kruzik }
360d7f81bf2SJakub Kruzik 
361793850ffSBarry Smith /*@
3628bd739bdSJakub Kruzik     MatCompositeAddMat - Add another matrix to a composite matrix.
363793850ffSBarry Smith 
364793850ffSBarry Smith    Collective on Mat
365793850ffSBarry Smith 
366793850ffSBarry Smith     Input Parameters:
367793850ffSBarry Smith +   mat - the composite matrix
368793850ffSBarry Smith -   smat - the partial matrix
369793850ffSBarry Smith 
370793850ffSBarry Smith    Level: advanced
371793850ffSBarry Smith 
3728bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
373793850ffSBarry Smith @*/
3747087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat)
375793850ffSBarry Smith {
376793850ffSBarry Smith   PetscErrorCode    ierr;
377793850ffSBarry Smith 
378793850ffSBarry Smith   PetscFunctionBegin;
3790700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3800700a824SBarry Smith   PetscValidHeaderSpecific(smat,MAT_CLASSID,2);
381d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr);
382d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
383d7f81bf2SJakub Kruzik }
384793850ffSBarry Smith 
385d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type)
386d7f81bf2SJakub Kruzik {
387d7f81bf2SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
388d7f81bf2SJakub Kruzik 
389d7f81bf2SJakub Kruzik   PetscFunctionBegin;
390ced1ac25SJakub Kruzik   b->type = type;
391d7f81bf2SJakub Kruzik   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
392d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = 0;
393d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite_Multiplicative;
394d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
395d7f81bf2SJakub Kruzik   } else {
396d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
397d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite;
398d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite;
399793850ffSBarry Smith   }
4006d7c1e57SBarry Smith   PetscFunctionReturn(0);
4016d7c1e57SBarry Smith }
4026d7c1e57SBarry Smith 
4032c0821f3SBarry Smith /*@
4048bd739bdSJakub Kruzik    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product.
4056d7c1e57SBarry Smith 
4066d7c1e57SBarry Smith   Collective on MPI_Comm
4076d7c1e57SBarry Smith 
4086d7c1e57SBarry Smith    Input Parameters:
4096d7c1e57SBarry Smith .  mat - the composite matrix
4106d7c1e57SBarry Smith 
4116d7c1e57SBarry Smith    Level: advanced
4126d7c1e57SBarry Smith 
4136dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE
4146d7c1e57SBarry Smith 
4156d7c1e57SBarry Smith @*/
4167087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type)
4176d7c1e57SBarry Smith {
4186d7c1e57SBarry Smith   PetscErrorCode ierr;
4196d7c1e57SBarry Smith 
4206d7c1e57SBarry Smith   PetscFunctionBegin;
421d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
422d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr);
423793850ffSBarry Smith   PetscFunctionReturn(0);
424793850ffSBarry Smith }
425793850ffSBarry Smith 
4266dbc55e5SJakub Kruzik static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type)
4276dbc55e5SJakub Kruzik {
4286dbc55e5SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
4296dbc55e5SJakub Kruzik 
4306dbc55e5SJakub Kruzik   PetscFunctionBegin;
4316dbc55e5SJakub Kruzik   *type = b->type;
4326dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4336dbc55e5SJakub Kruzik }
4346dbc55e5SJakub Kruzik 
4356dbc55e5SJakub Kruzik /*@
4366dbc55e5SJakub Kruzik    MatCompositeGetType - Returns type of composite.
4376dbc55e5SJakub Kruzik 
4386dbc55e5SJakub Kruzik    Not Collective
4396dbc55e5SJakub Kruzik 
4406dbc55e5SJakub Kruzik    Input Parameter:
4416dbc55e5SJakub Kruzik .  mat - the composite matrix
4426dbc55e5SJakub Kruzik 
4436dbc55e5SJakub Kruzik    Output Parameter:
4446dbc55e5SJakub Kruzik .  type - type of composite
4456dbc55e5SJakub Kruzik 
4466dbc55e5SJakub Kruzik    Level: advanced
4476dbc55e5SJakub Kruzik 
4486dbc55e5SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE
4496dbc55e5SJakub Kruzik 
4506dbc55e5SJakub Kruzik @*/
4516dbc55e5SJakub Kruzik PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type)
4526dbc55e5SJakub Kruzik {
4536dbc55e5SJakub Kruzik   PetscErrorCode ierr;
4546dbc55e5SJakub Kruzik 
4556dbc55e5SJakub Kruzik   PetscFunctionBegin;
4566dbc55e5SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4576dbc55e5SJakub Kruzik   PetscValidPointer(type,2);
4586dbc55e5SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr);
4596dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4606dbc55e5SJakub Kruzik }
4616dbc55e5SJakub Kruzik 
462d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat)
463b52f573bSBarry Smith {
464b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
4656d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head, prev = shell->tail;
466b52f573bSBarry Smith   PetscErrorCode    ierr;
4676d7c1e57SBarry Smith   Mat               tmat,newmat;
4681ba60692SJed Brown   Vec               left,right;
4691ba60692SJed Brown   PetscScalar       scale;
470b52f573bSBarry Smith 
471b52f573bSBarry Smith   PetscFunctionBegin;
472e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
473b52f573bSBarry Smith 
474b52f573bSBarry Smith   PetscFunctionBegin;
4756d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
476b52f573bSBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
477b52f573bSBarry Smith     while ((next = next->next)) {
478b52f573bSBarry Smith       ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
479b52f573bSBarry Smith     }
4806d7c1e57SBarry Smith   } else {
48104d534ceSJakub Kruzik     if (shell->mergefromright) {
4826d7c1e57SBarry Smith       ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
483b6cfcaf5SJakub Kruzik       while ((next = next->next)) {
484b6cfcaf5SJakub Kruzik         ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
4856bf464f9SBarry Smith         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4866d7c1e57SBarry Smith         tmat = newmat;
4876d7c1e57SBarry Smith       }
48804d534ceSJakub Kruzik     } else {
48904d534ceSJakub Kruzik       ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
49004d534ceSJakub Kruzik       while ((prev = prev->prev)) {
49104d534ceSJakub Kruzik         ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
49204d534ceSJakub Kruzik         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
49304d534ceSJakub Kruzik         tmat = newmat;
49404d534ceSJakub Kruzik       }
49504d534ceSJakub Kruzik     }
4966d7c1e57SBarry Smith   }
4971ba60692SJed Brown 
4981ba60692SJed Brown   scale = shell->scale;
4991ba60692SJed Brown   if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);}
5001ba60692SJed Brown   if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);}
5011ba60692SJed Brown 
50228be2f97SBarry Smith   ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr);
5031ba60692SJed Brown 
5041ba60692SJed Brown   ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr);
5051ba60692SJed Brown   ierr = MatScale(mat,scale);CHKERRQ(ierr);
5061ba60692SJed Brown   ierr = VecDestroy(&left);CHKERRQ(ierr);
5071ba60692SJed Brown   ierr = VecDestroy(&right);CHKERRQ(ierr);
508b52f573bSBarry Smith   PetscFunctionReturn(0);
509b52f573bSBarry Smith }
5106a7ede75SJakub Kruzik 
5116a7ede75SJakub Kruzik /*@
512d7f81bf2SJakub Kruzik    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
5138bd739bdSJakub Kruzik      by summing or computing the product of all the matrices inside the composite matrix.
514d7f81bf2SJakub Kruzik 
515d7f81bf2SJakub Kruzik   Collective on MPI_Comm
516d7f81bf2SJakub Kruzik 
517d7f81bf2SJakub Kruzik    Input Parameters:
518d7f81bf2SJakub Kruzik .  mat - the composite matrix
519d7f81bf2SJakub Kruzik 
520d7f81bf2SJakub Kruzik 
521d7f81bf2SJakub Kruzik    Options Database:
522d7f81bf2SJakub Kruzik .  -mat_composite_merge  (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked)
523d7f81bf2SJakub Kruzik 
524d7f81bf2SJakub Kruzik    Level: advanced
525d7f81bf2SJakub Kruzik 
526d7f81bf2SJakub Kruzik    Notes:
527d7f81bf2SJakub Kruzik       The MatType of the resulting matrix will be the same as the MatType of the FIRST
528d7f81bf2SJakub Kruzik     matrix in the composite matrix.
529d7f81bf2SJakub Kruzik 
53004d534ceSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMergeFromRight(), MATCOMPOSITE
531d7f81bf2SJakub Kruzik 
532d7f81bf2SJakub Kruzik @*/
533d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat)
534d7f81bf2SJakub Kruzik {
535d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
536d7f81bf2SJakub Kruzik 
537d7f81bf2SJakub Kruzik   PetscFunctionBegin;
538d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
539d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr);
540d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
541d7f81bf2SJakub Kruzik }
542d7f81bf2SJakub Kruzik 
543*6d0add67SJakub Kruzik static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat,PetscInt *nmat)
544d7f81bf2SJakub Kruzik {
545d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
546d7f81bf2SJakub Kruzik 
547d7f81bf2SJakub Kruzik   PetscFunctionBegin;
548d7f81bf2SJakub Kruzik   *nmat = shell->nmat;
549d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
550d7f81bf2SJakub Kruzik }
551d7f81bf2SJakub Kruzik 
552d7f81bf2SJakub Kruzik /*@
553*6d0add67SJakub Kruzik    MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix.
5546a7ede75SJakub Kruzik 
5556a7ede75SJakub Kruzik    Not Collective
5566a7ede75SJakub Kruzik 
5576a7ede75SJakub Kruzik    Input Parameter:
558d7f81bf2SJakub Kruzik .  mat - the composite matrix
5596a7ede75SJakub Kruzik 
5606a7ede75SJakub Kruzik    Output Parameter:
561*6d0add67SJakub Kruzik .  nmat - number of matrices in the composite matrix
5626a7ede75SJakub Kruzik 
5638b5c3584SJakub Kruzik    Level: advanced
5646a7ede75SJakub Kruzik 
5658bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
5666a7ede75SJakub Kruzik 
5676a7ede75SJakub Kruzik @*/
568*6d0add67SJakub Kruzik PetscErrorCode MatCompositeGetNumberMat(Mat mat,PetscInt *nmat)
5696a7ede75SJakub Kruzik {
570d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
5716a7ede75SJakub Kruzik 
5726a7ede75SJakub Kruzik   PetscFunctionBegin;
573d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5746a7ede75SJakub Kruzik   PetscValidPointer(nmat,2);
575*6d0add67SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetNumberMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr);
576d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
577d7f81bf2SJakub Kruzik }
578d7f81bf2SJakub Kruzik 
579d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai)
580d7f81bf2SJakub Kruzik {
581d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
582d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink;
583d7f81bf2SJakub Kruzik   PetscInt          k;
584d7f81bf2SJakub Kruzik 
585d7f81bf2SJakub Kruzik   PetscFunctionBegin;
586d7f81bf2SJakub Kruzik   if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat);
587d7f81bf2SJakub Kruzik   ilink = shell->head;
588d7f81bf2SJakub Kruzik   for (k=0; k<i; k++) {
589d7f81bf2SJakub Kruzik     ilink = ilink->next;
590d7f81bf2SJakub Kruzik   }
591d7f81bf2SJakub Kruzik   *Ai = ilink->mat;
5926a7ede75SJakub Kruzik   PetscFunctionReturn(0);
5936a7ede75SJakub Kruzik }
5946a7ede75SJakub Kruzik 
5958b5c3584SJakub Kruzik /*@
5968bd739bdSJakub Kruzik    MatCompositeGetMat - Returns the ith matrix from the composite matrix.
5978b5c3584SJakub Kruzik 
5988b5c3584SJakub Kruzik    Logically Collective on Mat
5998b5c3584SJakub Kruzik 
6008b5c3584SJakub Kruzik    Input Parameter:
601d7f81bf2SJakub Kruzik +  mat - the composite matrix
6028b5c3584SJakub Kruzik -  i - the number of requested matrix
6038b5c3584SJakub Kruzik 
6048b5c3584SJakub Kruzik    Output Parameter:
6058b5c3584SJakub Kruzik .  Ai - ith matrix in composite
6068b5c3584SJakub Kruzik 
6078b5c3584SJakub Kruzik    Level: advanced
6088b5c3584SJakub Kruzik 
609*6d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNumberMat(), MatCompositeAddMat(), MATCOMPOSITE
6108b5c3584SJakub Kruzik 
6118b5c3584SJakub Kruzik @*/
612d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai)
6138b5c3584SJakub Kruzik {
614d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
6158b5c3584SJakub Kruzik 
6168b5c3584SJakub Kruzik   PetscFunctionBegin;
617d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
618d7f81bf2SJakub Kruzik   PetscValidLogicalCollectiveInt(mat,i,2);
6198b5c3584SJakub Kruzik   PetscValidPointer(Ai,3);
620d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr);
6218b5c3584SJakub Kruzik   PetscFunctionReturn(0);
6228b5c3584SJakub Kruzik }
6238b5c3584SJakub Kruzik 
62404d534ceSJakub Kruzik static PetscErrorCode MatCompositeSetMergeFromRight_Composite(Mat mat,PetscBool flg)
62504d534ceSJakub Kruzik {
62604d534ceSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
62704d534ceSJakub Kruzik 
62804d534ceSJakub Kruzik   PetscFunctionBegin;
62904d534ceSJakub Kruzik   shell->mergefromright = flg;
63004d534ceSJakub Kruzik   PetscFunctionReturn(0);
63104d534ceSJakub Kruzik }
63204d534ceSJakub Kruzik 
63304d534ceSJakub Kruzik /*@
63404d534ceSJakub Kruzik    MatCompositeSetMergeFromRight - Sets MatCompositeMerge() to start from right.
63504d534ceSJakub Kruzik 
63604d534ceSJakub Kruzik    Logically Collective on Mat
63704d534ceSJakub Kruzik 
63804d534ceSJakub Kruzik    Input Parameter:
63904d534ceSJakub Kruzik +  mat - the composite matrix
64004d534ceSJakub Kruzik -  flg - if true (default) the merge starts with the first added matrix (mat[0])
64104d534ceSJakub Kruzik 
64204d534ceSJakub Kruzik    Level: advanced
64304d534ceSJakub Kruzik 
6448bd739bdSJakub Kruzik    Notes:
6458bd739bdSJakub Kruzik     Has an effect only if the composite matrix is multiplicative.
6468bd739bdSJakub Kruzik 
6478bd739bdSJakub Kruzik     The resulting matrix is the same regardles of the flg. Only the order of operation is changed.
6488bd739bdSJakub Kruzik     If flg is true the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0])))
6498bd739bdSJakub Kruzik     otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0].
6508bd739bdSJakub Kruzik 
6518bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE
65204d534ceSJakub Kruzik 
65304d534ceSJakub Kruzik @*/
65404d534ceSJakub Kruzik PetscErrorCode MatCompositeSetMergeFromRight(Mat mat,PetscBool flg)
65504d534ceSJakub Kruzik {
65604d534ceSJakub Kruzik   PetscErrorCode ierr;
65704d534ceSJakub Kruzik 
65804d534ceSJakub Kruzik   PetscFunctionBegin;
65904d534ceSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
66004d534ceSJakub Kruzik   PetscValidLogicalCollectiveBool(mat,flg,2);
66104d534ceSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetMergeFromRight_C",(Mat,PetscBool),(mat,flg));CHKERRQ(ierr);
66204d534ceSJakub Kruzik   PetscFunctionReturn(0);
66304d534ceSJakub Kruzik }
66404d534ceSJakub Kruzik 
66541cd0125SJakub Kruzik static struct _MatOps MatOps_Values = {0,
66641cd0125SJakub Kruzik                                        0,
66741cd0125SJakub Kruzik                                        0,
66841cd0125SJakub Kruzik                                        MatMult_Composite,
6697bf3a71bSJakub Kruzik                                        MatMultAdd_Composite,
67041cd0125SJakub Kruzik                                 /*  5*/ MatMultTranspose_Composite,
6717bf3a71bSJakub Kruzik                                        MatMultTransposeAdd_Composite,
67241cd0125SJakub Kruzik                                        0,
67341cd0125SJakub Kruzik                                        0,
67441cd0125SJakub Kruzik                                        0,
67541cd0125SJakub Kruzik                                 /* 10*/ 0,
67641cd0125SJakub Kruzik                                        0,
67741cd0125SJakub Kruzik                                        0,
67841cd0125SJakub Kruzik                                        0,
67941cd0125SJakub Kruzik                                        0,
68041cd0125SJakub Kruzik                                 /* 15*/ 0,
68141cd0125SJakub Kruzik                                        0,
68241cd0125SJakub Kruzik                                        MatGetDiagonal_Composite,
68341cd0125SJakub Kruzik                                        MatDiagonalScale_Composite,
68441cd0125SJakub Kruzik                                        0,
68541cd0125SJakub Kruzik                                 /* 20*/ 0,
68641cd0125SJakub Kruzik                                        MatAssemblyEnd_Composite,
68741cd0125SJakub Kruzik                                        0,
68841cd0125SJakub Kruzik                                        0,
68941cd0125SJakub Kruzik                                /* 24*/ 0,
69041cd0125SJakub Kruzik                                        0,
69141cd0125SJakub Kruzik                                        0,
69241cd0125SJakub Kruzik                                        0,
69341cd0125SJakub Kruzik                                        0,
69441cd0125SJakub Kruzik                                /* 29*/ 0,
69541cd0125SJakub Kruzik                                        0,
69641cd0125SJakub Kruzik                                        0,
69741cd0125SJakub Kruzik                                        0,
69841cd0125SJakub Kruzik                                        0,
69941cd0125SJakub Kruzik                                /* 34*/ 0,
70041cd0125SJakub Kruzik                                        0,
70141cd0125SJakub Kruzik                                        0,
70241cd0125SJakub Kruzik                                        0,
70341cd0125SJakub Kruzik                                        0,
70441cd0125SJakub Kruzik                                /* 39*/ 0,
70541cd0125SJakub Kruzik                                        0,
70641cd0125SJakub Kruzik                                        0,
70741cd0125SJakub Kruzik                                        0,
70841cd0125SJakub Kruzik                                        0,
70941cd0125SJakub Kruzik                                /* 44*/ 0,
71041cd0125SJakub Kruzik                                        MatScale_Composite,
71141cd0125SJakub Kruzik                                        MatShift_Basic,
71241cd0125SJakub Kruzik                                        0,
71341cd0125SJakub Kruzik                                        0,
71441cd0125SJakub Kruzik                                /* 49*/ 0,
71541cd0125SJakub Kruzik                                        0,
71641cd0125SJakub Kruzik                                        0,
71741cd0125SJakub Kruzik                                        0,
71841cd0125SJakub Kruzik                                        0,
71941cd0125SJakub Kruzik                                /* 54*/ 0,
72041cd0125SJakub Kruzik                                        0,
72141cd0125SJakub Kruzik                                        0,
72241cd0125SJakub Kruzik                                        0,
72341cd0125SJakub Kruzik                                        0,
72441cd0125SJakub Kruzik                                /* 59*/ 0,
72541cd0125SJakub Kruzik                                        MatDestroy_Composite,
72641cd0125SJakub Kruzik                                        0,
72741cd0125SJakub Kruzik                                        0,
72841cd0125SJakub Kruzik                                        0,
72941cd0125SJakub Kruzik                                /* 64*/ 0,
73041cd0125SJakub Kruzik                                        0,
73141cd0125SJakub Kruzik                                        0,
73241cd0125SJakub Kruzik                                        0,
73341cd0125SJakub Kruzik                                        0,
73441cd0125SJakub Kruzik                                /* 69*/ 0,
73541cd0125SJakub Kruzik                                        0,
73641cd0125SJakub Kruzik                                        0,
73741cd0125SJakub Kruzik                                        0,
73841cd0125SJakub Kruzik                                        0,
73941cd0125SJakub Kruzik                                /* 74*/ 0,
74041cd0125SJakub Kruzik                                        0,
74141cd0125SJakub Kruzik                                        0,
74241cd0125SJakub Kruzik                                        0,
74341cd0125SJakub Kruzik                                        0,
74441cd0125SJakub Kruzik                                /* 79*/ 0,
74541cd0125SJakub Kruzik                                        0,
74641cd0125SJakub Kruzik                                        0,
74741cd0125SJakub Kruzik                                        0,
74841cd0125SJakub Kruzik                                        0,
74941cd0125SJakub Kruzik                                /* 84*/ 0,
75041cd0125SJakub Kruzik                                        0,
75141cd0125SJakub Kruzik                                        0,
75241cd0125SJakub Kruzik                                        0,
75341cd0125SJakub Kruzik                                        0,
75441cd0125SJakub Kruzik                                /* 89*/ 0,
75541cd0125SJakub Kruzik                                        0,
75641cd0125SJakub Kruzik                                        0,
75741cd0125SJakub Kruzik                                        0,
75841cd0125SJakub Kruzik                                        0,
75941cd0125SJakub Kruzik                                /* 94*/ 0,
76041cd0125SJakub Kruzik                                        0,
76141cd0125SJakub Kruzik                                        0,
76241cd0125SJakub Kruzik                                        0,
76341cd0125SJakub Kruzik                                        0,
76441cd0125SJakub Kruzik                                 /*99*/ 0,
76541cd0125SJakub Kruzik                                        0,
76641cd0125SJakub Kruzik                                        0,
76741cd0125SJakub Kruzik                                        0,
76841cd0125SJakub Kruzik                                        0,
76941cd0125SJakub Kruzik                                /*104*/ 0,
77041cd0125SJakub Kruzik                                        0,
77141cd0125SJakub Kruzik                                        0,
77241cd0125SJakub Kruzik                                        0,
77341cd0125SJakub Kruzik                                        0,
77441cd0125SJakub Kruzik                                /*109*/ 0,
77541cd0125SJakub Kruzik                                        0,
77641cd0125SJakub Kruzik                                        0,
77741cd0125SJakub Kruzik                                        0,
77841cd0125SJakub Kruzik                                        0,
77941cd0125SJakub Kruzik                                /*114*/ 0,
78041cd0125SJakub Kruzik                                        0,
78141cd0125SJakub Kruzik                                        0,
78241cd0125SJakub Kruzik                                        0,
78341cd0125SJakub Kruzik                                        0,
78441cd0125SJakub Kruzik                                /*119*/ 0,
78541cd0125SJakub Kruzik                                        0,
78641cd0125SJakub Kruzik                                        0,
78741cd0125SJakub Kruzik                                        0,
78841cd0125SJakub Kruzik                                        0,
78941cd0125SJakub Kruzik                                /*124*/ 0,
79041cd0125SJakub Kruzik                                        0,
79141cd0125SJakub Kruzik                                        0,
79241cd0125SJakub Kruzik                                        0,
79341cd0125SJakub Kruzik                                        0,
79441cd0125SJakub Kruzik                                /*129*/ 0,
79541cd0125SJakub Kruzik                                        0,
79641cd0125SJakub Kruzik                                        0,
79741cd0125SJakub Kruzik                                        0,
79841cd0125SJakub Kruzik                                        0,
79941cd0125SJakub Kruzik                                /*134*/ 0,
80041cd0125SJakub Kruzik                                        0,
80141cd0125SJakub Kruzik                                        0,
80241cd0125SJakub Kruzik                                        0,
80341cd0125SJakub Kruzik                                        0,
80441cd0125SJakub Kruzik                                /*139*/ 0,
80541cd0125SJakub Kruzik                                        0,
80641cd0125SJakub Kruzik                                        0
80741cd0125SJakub Kruzik };
80841cd0125SJakub Kruzik 
80941cd0125SJakub Kruzik /*MC
81041cd0125SJakub Kruzik    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices.
81141cd0125SJakub Kruzik     The matrices need to have a correct size and parallel layout for the sum or product to be valid.
81241cd0125SJakub Kruzik 
81341cd0125SJakub Kruzik    Notes:
81441cd0125SJakub Kruzik     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
81541cd0125SJakub Kruzik 
81641cd0125SJakub Kruzik   Level: advanced
81741cd0125SJakub Kruzik 
818*6d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeMerge(), MatCompositeSetMergeFromRight(), MatCompositeGetNumberMat(), MatCompositeGetMat()
81941cd0125SJakub Kruzik M*/
82041cd0125SJakub Kruzik 
82141cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A)
82241cd0125SJakub Kruzik {
82341cd0125SJakub Kruzik   Mat_Composite  *b;
82441cd0125SJakub Kruzik   PetscErrorCode ierr;
82541cd0125SJakub Kruzik 
82641cd0125SJakub Kruzik   PetscFunctionBegin;
82741cd0125SJakub Kruzik   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
82841cd0125SJakub Kruzik   A->data = (void*)b;
82941cd0125SJakub Kruzik   ierr    = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
83041cd0125SJakub Kruzik 
83141cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
83241cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
83341cd0125SJakub Kruzik 
83441cd0125SJakub Kruzik   A->assembled      = PETSC_TRUE;
83541cd0125SJakub Kruzik   A->preallocated   = PETSC_TRUE;
83641cd0125SJakub Kruzik   b->type           = MAT_COMPOSITE_ADDITIVE;
83741cd0125SJakub Kruzik   b->scale          = 1.0;
83841cd0125SJakub Kruzik   b->nmat           = 0;
83904d534ceSJakub Kruzik   b->mergefromright = PETSC_TRUE;
84041cd0125SJakub Kruzik 
84141cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr);
84241cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr);
8436dbc55e5SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr);
84441cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr);
845*6d0add67SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNumberMat_C",MatCompositeGetNumberMat_Composite);CHKERRQ(ierr);
84641cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr);
84704d534ceSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeFromRight_C",MatCompositeSetMergeFromRight_Composite);CHKERRQ(ierr);
84841cd0125SJakub Kruzik 
84941cd0125SJakub Kruzik   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
85041cd0125SJakub Kruzik   PetscFunctionReturn(0);
85141cd0125SJakub Kruzik }
85241cd0125SJakub Kruzik 
853