xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 4b2558d635d1a9bb5b6b39c7ef286fb42cdd6eb8)
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;
19*4b2558d6SJakub Kruzik   PetscBool         merge;
2004d534ceSJakub Kruzik   PetscBool         mergefromright;
21793850ffSBarry Smith } Mat_Composite;
22793850ffSBarry Smith 
23793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
24793850ffSBarry Smith {
25793850ffSBarry Smith   PetscErrorCode    ierr;
262c33bbaeSSatish Balay   Mat_Composite     *shell = (Mat_Composite*)mat->data;
276d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head,oldnext;
28793850ffSBarry Smith 
29793850ffSBarry Smith   PetscFunctionBegin;
30793850ffSBarry Smith   while (next) {
316bf464f9SBarry Smith     ierr = MatDestroy(&next->mat);CHKERRQ(ierr);
326d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
336bf464f9SBarry Smith       ierr = VecDestroy(&next->work);CHKERRQ(ierr);
346d7c1e57SBarry Smith     }
356d7c1e57SBarry Smith     oldnext = next;
36793850ffSBarry Smith     next    = next->next;
376d7c1e57SBarry Smith     ierr    = PetscFree(oldnext);CHKERRQ(ierr);
38793850ffSBarry Smith   }
396bf464f9SBarry Smith   ierr = VecDestroy(&shell->work);CHKERRQ(ierr);
406bf464f9SBarry Smith   ierr = VecDestroy(&shell->left);CHKERRQ(ierr);
416bf464f9SBarry Smith   ierr = VecDestroy(&shell->right);CHKERRQ(ierr);
426bf464f9SBarry Smith   ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr);
436bf464f9SBarry Smith   ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr);
446bf464f9SBarry Smith   ierr = PetscFree(mat->data);CHKERRQ(ierr);
45793850ffSBarry Smith   PetscFunctionReturn(0);
46793850ffSBarry Smith }
47793850ffSBarry Smith 
486d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
496d7c1e57SBarry Smith {
506d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
516d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head;
526d7c1e57SBarry Smith   PetscErrorCode    ierr;
536d7c1e57SBarry Smith   Vec               in,out;
546d7c1e57SBarry Smith 
556d7c1e57SBarry Smith   PetscFunctionBegin;
56e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
576d7c1e57SBarry Smith   in = x;
58e4fc5df0SBarry Smith   if (shell->right) {
59e4fc5df0SBarry Smith     if (!shell->rightwork) {
60e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
61e4fc5df0SBarry Smith     }
62e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
63e4fc5df0SBarry Smith     in   = shell->rightwork;
64e4fc5df0SBarry Smith   }
656d7c1e57SBarry Smith   while (next->next) {
666d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
672a7a6963SBarry Smith       ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr);
686d7c1e57SBarry Smith     }
696d7c1e57SBarry Smith     out  = next->work;
706d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
716d7c1e57SBarry Smith     in   = out;
726d7c1e57SBarry Smith     next = next->next;
736d7c1e57SBarry Smith   }
746d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
75e4fc5df0SBarry Smith   if (shell->left) {
76e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
77e4fc5df0SBarry Smith   }
78e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
796d7c1e57SBarry Smith   PetscFunctionReturn(0);
806d7c1e57SBarry Smith }
816d7c1e57SBarry Smith 
826d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
836d7c1e57SBarry Smith {
846d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
856d7c1e57SBarry Smith   Mat_CompositeLink tail   = shell->tail;
866d7c1e57SBarry Smith   PetscErrorCode    ierr;
876d7c1e57SBarry Smith   Vec               in,out;
886d7c1e57SBarry Smith 
896d7c1e57SBarry Smith   PetscFunctionBegin;
90e32f2f54SBarry Smith   if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
916d7c1e57SBarry Smith   in = x;
92e4fc5df0SBarry Smith   if (shell->left) {
93e4fc5df0SBarry Smith     if (!shell->leftwork) {
94e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
95e4fc5df0SBarry Smith     }
96e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
97e4fc5df0SBarry Smith     in   = shell->leftwork;
98e4fc5df0SBarry Smith   }
996d7c1e57SBarry Smith   while (tail->prev) {
1006d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
1012a7a6963SBarry Smith       ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr);
1026d7c1e57SBarry Smith     }
1036d7c1e57SBarry Smith     out  = tail->prev->work;
1046d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
1056d7c1e57SBarry Smith     in   = out;
1066d7c1e57SBarry Smith     tail = tail->prev;
1076d7c1e57SBarry Smith   }
1086d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
109e4fc5df0SBarry Smith   if (shell->right) {
110e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
111e4fc5df0SBarry Smith   }
112e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
1136d7c1e57SBarry Smith   PetscFunctionReturn(0);
1146d7c1e57SBarry Smith }
1156d7c1e57SBarry Smith 
116793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
117793850ffSBarry Smith {
118793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
119793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
120793850ffSBarry Smith   PetscErrorCode    ierr;
121e4fc5df0SBarry Smith   Vec               in;
122793850ffSBarry Smith 
123793850ffSBarry Smith   PetscFunctionBegin;
124e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
125e4fc5df0SBarry Smith   in = x;
126e4fc5df0SBarry Smith   if (shell->right) {
127e4fc5df0SBarry Smith     if (!shell->rightwork) {
128e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
129793850ffSBarry Smith     }
130e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
131e4fc5df0SBarry Smith     in   = shell->rightwork;
132e4fc5df0SBarry Smith   }
133e4fc5df0SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
134e4fc5df0SBarry Smith   while ((next = next->next)) {
135e4fc5df0SBarry Smith     ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr);
136e4fc5df0SBarry Smith   }
137e4fc5df0SBarry Smith   if (shell->left) {
138e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
139e4fc5df0SBarry Smith   }
140e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
141793850ffSBarry Smith   PetscFunctionReturn(0);
142793850ffSBarry Smith }
143793850ffSBarry Smith 
144793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
145793850ffSBarry Smith {
146793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
147793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
148793850ffSBarry Smith   PetscErrorCode    ierr;
149e4fc5df0SBarry Smith   Vec               in;
150793850ffSBarry Smith 
151793850ffSBarry Smith   PetscFunctionBegin;
152e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
153e4fc5df0SBarry Smith   in = x;
154e4fc5df0SBarry Smith   if (shell->left) {
155e4fc5df0SBarry Smith     if (!shell->leftwork) {
156e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
157793850ffSBarry Smith     }
158e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
159e4fc5df0SBarry Smith     in   = shell->leftwork;
160e4fc5df0SBarry Smith   }
161e4fc5df0SBarry Smith   ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr);
162e4fc5df0SBarry Smith   while ((next = next->next)) {
163e4fc5df0SBarry Smith     ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr);
164e4fc5df0SBarry Smith   }
165e4fc5df0SBarry Smith   if (shell->right) {
166e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
167e4fc5df0SBarry Smith   }
168e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
169793850ffSBarry Smith   PetscFunctionReturn(0);
170793850ffSBarry Smith }
171793850ffSBarry Smith 
1727bf3a71bSJakub Kruzik PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z)
1737bf3a71bSJakub Kruzik {
1747bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1757bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1767bf3a71bSJakub Kruzik 
1777bf3a71bSJakub Kruzik   PetscFunctionBegin;
1787bf3a71bSJakub Kruzik   if (y != z) {
1797bf3a71bSJakub Kruzik     ierr = MatMult(A,x,z);CHKERRQ(ierr);
1807bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
1817bf3a71bSJakub Kruzik   } else {
1827bf3a71bSJakub Kruzik     if (!shell->leftwork) {
1837bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr);
1847bf3a71bSJakub Kruzik     }
1857bf3a71bSJakub Kruzik     ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr);
1867bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
1877bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr);
1887bf3a71bSJakub Kruzik   }
1897bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
1907bf3a71bSJakub Kruzik }
1917bf3a71bSJakub Kruzik 
1927bf3a71bSJakub Kruzik PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z)
1937bf3a71bSJakub Kruzik {
1947bf3a71bSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)A->data;
1957bf3a71bSJakub Kruzik   PetscErrorCode    ierr;
1967bf3a71bSJakub Kruzik 
1977bf3a71bSJakub Kruzik   PetscFunctionBegin;
1987bf3a71bSJakub Kruzik   if (y != z) {
1997bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr);
2007bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
2017bf3a71bSJakub Kruzik   } else {
2027bf3a71bSJakub Kruzik     if (!shell->rightwork) {
2037bf3a71bSJakub Kruzik       ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr);
2047bf3a71bSJakub Kruzik     }
2057bf3a71bSJakub Kruzik     ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr);
2067bf3a71bSJakub Kruzik     ierr = VecCopy(y,z);CHKERRQ(ierr);
2077bf3a71bSJakub Kruzik     ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr);
2087bf3a71bSJakub Kruzik   }
2097bf3a71bSJakub Kruzik   PetscFunctionReturn(0);
2107bf3a71bSJakub Kruzik }
2117bf3a71bSJakub Kruzik 
212793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
213793850ffSBarry Smith {
214793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
215793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
216793850ffSBarry Smith   PetscErrorCode    ierr;
217793850ffSBarry Smith 
218793850ffSBarry Smith   PetscFunctionBegin;
219e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
220e32f2f54SBarry Smith   if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling");
221e4fc5df0SBarry Smith 
222793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
223793850ffSBarry Smith   if (next->next && !shell->work) {
224793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
225793850ffSBarry Smith   }
226793850ffSBarry Smith   while ((next = next->next)) {
227793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
228793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
229793850ffSBarry Smith   }
230e4fc5df0SBarry Smith   ierr = VecScale(v,shell->scale);CHKERRQ(ierr);
231793850ffSBarry Smith   PetscFunctionReturn(0);
232793850ffSBarry Smith }
233793850ffSBarry Smith 
234793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
235793850ffSBarry Smith {
236*4b2558d6SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)Y->data;
237b52f573bSBarry Smith   PetscErrorCode    ierr;
238b52f573bSBarry Smith 
239793850ffSBarry Smith   PetscFunctionBegin;
240*4b2558d6SJakub Kruzik   if (shell->merge) {
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 
280*4b2558d6SJakub Kruzik PetscErrorCode MatSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,Mat A)
281*4b2558d6SJakub Kruzik {
282*4b2558d6SJakub Kruzik   Mat_Composite  *a = (Mat_Composite*)A->data;
283*4b2558d6SJakub Kruzik   PetscErrorCode ierr;
284*4b2558d6SJakub Kruzik 
285*4b2558d6SJakub Kruzik   PetscFunctionBegin;
286*4b2558d6SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"MATCOMPOSITE options");CHKERRQ(ierr);
287*4b2558d6SJakub Kruzik   ierr = PetscOptionsBool("-mat_composite_merge","Merge at MatAssemblyEnd","MatCompositeMerge",a->merge,&a->merge,NULL);CHKERRQ(ierr);
288*4b2558d6SJakub Kruzik   ierr = PetscOptionsBool("-mat_composite_merge_from_right","Set direction of merge","MatCompositeSetMergeFromRight",a->mergefromright,&a->mergefromright,NULL);CHKERRQ(ierr);
289*4b2558d6SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
290*4b2558d6SJakub Kruzik   PetscFunctionReturn(0);
291*4b2558d6SJakub Kruzik }
292*4b2558d6SJakub Kruzik 
2932c0821f3SBarry Smith /*@
2948bd739bdSJakub Kruzik    MatCreateComposite - Creates a matrix as the sum or product of one or more matrices
295793850ffSBarry Smith 
296793850ffSBarry Smith   Collective on MPI_Comm
297793850ffSBarry Smith 
298793850ffSBarry Smith    Input Parameters:
299793850ffSBarry Smith +  comm - MPI communicator
300793850ffSBarry Smith .  nmat - number of matrices to put in
301793850ffSBarry Smith -  mats - the matrices
302793850ffSBarry Smith 
303793850ffSBarry Smith    Output Parameter:
304db36af27SMatthew G. Knepley .  mat - the matrix
305793850ffSBarry Smith 
306*4b2558d6SJakub Kruzik    Options Database Keys:
307*4b2558d6SJakub Kruzik +  -mat_composite_merge - merge in MatAssemblyEnd()
308*4b2558d6SJakub Kruzik -  -mat_composite_merge_from_right - merge starts from right
309*4b2558d6SJakub Kruzik 
310793850ffSBarry Smith    Level: advanced
311793850ffSBarry Smith 
312793850ffSBarry Smith    Notes:
313793850ffSBarry Smith      Alternative construction
314793850ffSBarry Smith $       MatCreate(comm,&mat);
315793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
316793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
317793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
318793850ffSBarry Smith $       ....
319793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
320b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
321b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
322793850ffSBarry Smith 
3236d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
3246d7c1e57SBarry Smith 
3256dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE
326793850ffSBarry Smith 
327793850ffSBarry Smith @*/
3287087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
329793850ffSBarry Smith {
330793850ffSBarry Smith   PetscErrorCode ierr;
331793850ffSBarry Smith   PetscInt       m,n,M,N,i;
332793850ffSBarry Smith 
333793850ffSBarry Smith   PetscFunctionBegin;
334e32f2f54SBarry Smith   if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
335f3f84630SBarry Smith   PetscValidPointer(mat,3);
336793850ffSBarry Smith 
337c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr);
338c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr);
339c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr);
340c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr);
341793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
342793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
343793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
344793850ffSBarry Smith   for (i=0; i<nmat; i++) {
345793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
346793850ffSBarry Smith   }
347b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
348b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
349793850ffSBarry Smith   PetscFunctionReturn(0);
350793850ffSBarry Smith }
351793850ffSBarry Smith 
352d7f81bf2SJakub Kruzik 
353d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat)
354d7f81bf2SJakub Kruzik {
355d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
356d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink,next = shell->head;
357d7f81bf2SJakub Kruzik   PetscErrorCode    ierr;
358d7f81bf2SJakub Kruzik 
359d7f81bf2SJakub Kruzik   PetscFunctionBegin;
360d7f81bf2SJakub Kruzik   ierr        = PetscNewLog(mat,&ilink);CHKERRQ(ierr);
361d7f81bf2SJakub Kruzik   ilink->next = 0;
362d7f81bf2SJakub Kruzik   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
363d7f81bf2SJakub Kruzik   ilink->mat  = smat;
364d7f81bf2SJakub Kruzik 
365d7f81bf2SJakub Kruzik   if (!next) shell->head = ilink;
366d7f81bf2SJakub Kruzik   else {
367d7f81bf2SJakub Kruzik     while (next->next) {
368d7f81bf2SJakub Kruzik       next = next->next;
369d7f81bf2SJakub Kruzik     }
370d7f81bf2SJakub Kruzik     next->next  = ilink;
371d7f81bf2SJakub Kruzik     ilink->prev = next;
372d7f81bf2SJakub Kruzik   }
373d7f81bf2SJakub Kruzik   shell->tail =  ilink;
374d7f81bf2SJakub Kruzik   shell->nmat += 1;
375d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
376d7f81bf2SJakub Kruzik }
377d7f81bf2SJakub Kruzik 
378793850ffSBarry Smith /*@
3798bd739bdSJakub Kruzik     MatCompositeAddMat - Add another matrix to a composite matrix.
380793850ffSBarry Smith 
381793850ffSBarry Smith    Collective on Mat
382793850ffSBarry Smith 
383793850ffSBarry Smith     Input Parameters:
384793850ffSBarry Smith +   mat - the composite matrix
385793850ffSBarry Smith -   smat - the partial matrix
386793850ffSBarry Smith 
387793850ffSBarry Smith    Level: advanced
388793850ffSBarry Smith 
3898bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
390793850ffSBarry Smith @*/
3917087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat)
392793850ffSBarry Smith {
393793850ffSBarry Smith   PetscErrorCode    ierr;
394793850ffSBarry Smith 
395793850ffSBarry Smith   PetscFunctionBegin;
3960700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3970700a824SBarry Smith   PetscValidHeaderSpecific(smat,MAT_CLASSID,2);
398d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr);
399d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
400d7f81bf2SJakub Kruzik }
401793850ffSBarry Smith 
402d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type)
403d7f81bf2SJakub Kruzik {
404d7f81bf2SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
405d7f81bf2SJakub Kruzik 
406d7f81bf2SJakub Kruzik   PetscFunctionBegin;
407ced1ac25SJakub Kruzik   b->type = type;
408d7f81bf2SJakub Kruzik   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
409d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = 0;
410d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite_Multiplicative;
411d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
412d7f81bf2SJakub Kruzik   } else {
413d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
414d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite;
415d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite;
416793850ffSBarry Smith   }
4176d7c1e57SBarry Smith   PetscFunctionReturn(0);
4186d7c1e57SBarry Smith }
4196d7c1e57SBarry Smith 
4202c0821f3SBarry Smith /*@
4218bd739bdSJakub Kruzik    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product.
4226d7c1e57SBarry Smith 
4236d7c1e57SBarry Smith   Collective on MPI_Comm
4246d7c1e57SBarry Smith 
4256d7c1e57SBarry Smith    Input Parameters:
4266d7c1e57SBarry Smith .  mat - the composite matrix
4276d7c1e57SBarry Smith 
4286d7c1e57SBarry Smith    Level: advanced
4296d7c1e57SBarry Smith 
4306dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE
4316d7c1e57SBarry Smith 
4326d7c1e57SBarry Smith @*/
4337087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type)
4346d7c1e57SBarry Smith {
4356d7c1e57SBarry Smith   PetscErrorCode ierr;
4366d7c1e57SBarry Smith 
4376d7c1e57SBarry Smith   PetscFunctionBegin;
438d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
439d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr);
440793850ffSBarry Smith   PetscFunctionReturn(0);
441793850ffSBarry Smith }
442793850ffSBarry Smith 
4436dbc55e5SJakub Kruzik static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type)
4446dbc55e5SJakub Kruzik {
4456dbc55e5SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
4466dbc55e5SJakub Kruzik 
4476dbc55e5SJakub Kruzik   PetscFunctionBegin;
4486dbc55e5SJakub Kruzik   *type = b->type;
4496dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4506dbc55e5SJakub Kruzik }
4516dbc55e5SJakub Kruzik 
4526dbc55e5SJakub Kruzik /*@
4536dbc55e5SJakub Kruzik    MatCompositeGetType - Returns type of composite.
4546dbc55e5SJakub Kruzik 
4556dbc55e5SJakub Kruzik    Not Collective
4566dbc55e5SJakub Kruzik 
4576dbc55e5SJakub Kruzik    Input Parameter:
4586dbc55e5SJakub Kruzik .  mat - the composite matrix
4596dbc55e5SJakub Kruzik 
4606dbc55e5SJakub Kruzik    Output Parameter:
4616dbc55e5SJakub Kruzik .  type - type of composite
4626dbc55e5SJakub Kruzik 
4636dbc55e5SJakub Kruzik    Level: advanced
4646dbc55e5SJakub Kruzik 
4656dbc55e5SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE
4666dbc55e5SJakub Kruzik 
4676dbc55e5SJakub Kruzik @*/
4686dbc55e5SJakub Kruzik PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type)
4696dbc55e5SJakub Kruzik {
4706dbc55e5SJakub Kruzik   PetscErrorCode ierr;
4716dbc55e5SJakub Kruzik 
4726dbc55e5SJakub Kruzik   PetscFunctionBegin;
4736dbc55e5SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4746dbc55e5SJakub Kruzik   PetscValidPointer(type,2);
4756dbc55e5SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr);
4766dbc55e5SJakub Kruzik   PetscFunctionReturn(0);
4776dbc55e5SJakub Kruzik }
4786dbc55e5SJakub Kruzik 
479d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat)
480b52f573bSBarry Smith {
481b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
4826d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head, prev = shell->tail;
483b52f573bSBarry Smith   PetscErrorCode    ierr;
4846d7c1e57SBarry Smith   Mat               tmat,newmat;
4851ba60692SJed Brown   Vec               left,right;
4861ba60692SJed Brown   PetscScalar       scale;
487b52f573bSBarry Smith 
488b52f573bSBarry Smith   PetscFunctionBegin;
489e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
490b52f573bSBarry Smith 
491b52f573bSBarry Smith   PetscFunctionBegin;
4926d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
493b52f573bSBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
494b52f573bSBarry Smith     while ((next = next->next)) {
495b52f573bSBarry Smith       ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
496b52f573bSBarry Smith     }
4976d7c1e57SBarry Smith   } else {
49804d534ceSJakub Kruzik     if (shell->mergefromright) {
4996d7c1e57SBarry Smith       ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
500b6cfcaf5SJakub Kruzik       while ((next = next->next)) {
501b6cfcaf5SJakub Kruzik         ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
5026bf464f9SBarry Smith         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5036d7c1e57SBarry Smith         tmat = newmat;
5046d7c1e57SBarry Smith       }
50504d534ceSJakub Kruzik     } else {
50604d534ceSJakub Kruzik       ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
50704d534ceSJakub Kruzik       while ((prev = prev->prev)) {
50804d534ceSJakub Kruzik         ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
50904d534ceSJakub Kruzik         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
51004d534ceSJakub Kruzik         tmat = newmat;
51104d534ceSJakub Kruzik       }
51204d534ceSJakub Kruzik     }
5136d7c1e57SBarry Smith   }
5141ba60692SJed Brown 
5151ba60692SJed Brown   scale = shell->scale;
5161ba60692SJed Brown   if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);}
5171ba60692SJed Brown   if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);}
5181ba60692SJed Brown 
51928be2f97SBarry Smith   ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr);
5201ba60692SJed Brown 
5211ba60692SJed Brown   ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr);
5221ba60692SJed Brown   ierr = MatScale(mat,scale);CHKERRQ(ierr);
5231ba60692SJed Brown   ierr = VecDestroy(&left);CHKERRQ(ierr);
5241ba60692SJed Brown   ierr = VecDestroy(&right);CHKERRQ(ierr);
525b52f573bSBarry Smith   PetscFunctionReturn(0);
526b52f573bSBarry Smith }
5276a7ede75SJakub Kruzik 
5286a7ede75SJakub Kruzik /*@
529d7f81bf2SJakub Kruzik    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
5308bd739bdSJakub Kruzik      by summing or computing the product of all the matrices inside the composite matrix.
531d7f81bf2SJakub Kruzik 
532d7f81bf2SJakub Kruzik   Collective on MPI_Comm
533d7f81bf2SJakub Kruzik 
534d7f81bf2SJakub Kruzik    Input Parameters:
535d7f81bf2SJakub Kruzik .  mat - the composite matrix
536d7f81bf2SJakub Kruzik 
537d7f81bf2SJakub Kruzik 
538*4b2558d6SJakub Kruzik    Options Database Keys:
539*4b2558d6SJakub Kruzik .  -mat_composite_merge - merge in MatAssemblyEnd()
540d7f81bf2SJakub Kruzik 
541d7f81bf2SJakub Kruzik    Level: advanced
542d7f81bf2SJakub Kruzik 
543d7f81bf2SJakub Kruzik    Notes:
544d7f81bf2SJakub Kruzik       The MatType of the resulting matrix will be the same as the MatType of the FIRST
545d7f81bf2SJakub Kruzik     matrix in the composite matrix.
546d7f81bf2SJakub Kruzik 
54704d534ceSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMergeFromRight(), MATCOMPOSITE
548d7f81bf2SJakub Kruzik 
549d7f81bf2SJakub Kruzik @*/
550d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat)
551d7f81bf2SJakub Kruzik {
552d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
553d7f81bf2SJakub Kruzik 
554d7f81bf2SJakub Kruzik   PetscFunctionBegin;
555d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
556d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr);
557d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
558d7f81bf2SJakub Kruzik }
559d7f81bf2SJakub Kruzik 
5606d0add67SJakub Kruzik static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat,PetscInt *nmat)
561d7f81bf2SJakub Kruzik {
562d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
563d7f81bf2SJakub Kruzik 
564d7f81bf2SJakub Kruzik   PetscFunctionBegin;
565d7f81bf2SJakub Kruzik   *nmat = shell->nmat;
566d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
567d7f81bf2SJakub Kruzik }
568d7f81bf2SJakub Kruzik 
569d7f81bf2SJakub Kruzik /*@
5706d0add67SJakub Kruzik    MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix.
5716a7ede75SJakub Kruzik 
5726a7ede75SJakub Kruzik    Not Collective
5736a7ede75SJakub Kruzik 
5746a7ede75SJakub Kruzik    Input Parameter:
575d7f81bf2SJakub Kruzik .  mat - the composite matrix
5766a7ede75SJakub Kruzik 
5776a7ede75SJakub Kruzik    Output Parameter:
5786d0add67SJakub Kruzik .  nmat - number of matrices in the composite matrix
5796a7ede75SJakub Kruzik 
5808b5c3584SJakub Kruzik    Level: advanced
5816a7ede75SJakub Kruzik 
5828bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE
5836a7ede75SJakub Kruzik 
5846a7ede75SJakub Kruzik @*/
5856d0add67SJakub Kruzik PetscErrorCode MatCompositeGetNumberMat(Mat mat,PetscInt *nmat)
5866a7ede75SJakub Kruzik {
587d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
5886a7ede75SJakub Kruzik 
5896a7ede75SJakub Kruzik   PetscFunctionBegin;
590d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5916a7ede75SJakub Kruzik   PetscValidPointer(nmat,2);
5926d0add67SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetNumberMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr);
593d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
594d7f81bf2SJakub Kruzik }
595d7f81bf2SJakub Kruzik 
596d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai)
597d7f81bf2SJakub Kruzik {
598d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
599d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink;
600d7f81bf2SJakub Kruzik   PetscInt          k;
601d7f81bf2SJakub Kruzik 
602d7f81bf2SJakub Kruzik   PetscFunctionBegin;
603d7f81bf2SJakub Kruzik   if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat);
604d7f81bf2SJakub Kruzik   ilink = shell->head;
605d7f81bf2SJakub Kruzik   for (k=0; k<i; k++) {
606d7f81bf2SJakub Kruzik     ilink = ilink->next;
607d7f81bf2SJakub Kruzik   }
608d7f81bf2SJakub Kruzik   *Ai = ilink->mat;
6096a7ede75SJakub Kruzik   PetscFunctionReturn(0);
6106a7ede75SJakub Kruzik }
6116a7ede75SJakub Kruzik 
6128b5c3584SJakub Kruzik /*@
6138bd739bdSJakub Kruzik    MatCompositeGetMat - Returns the ith matrix from the composite matrix.
6148b5c3584SJakub Kruzik 
6158b5c3584SJakub Kruzik    Logically Collective on Mat
6168b5c3584SJakub Kruzik 
6178b5c3584SJakub Kruzik    Input Parameter:
618d7f81bf2SJakub Kruzik +  mat - the composite matrix
6198b5c3584SJakub Kruzik -  i - the number of requested matrix
6208b5c3584SJakub Kruzik 
6218b5c3584SJakub Kruzik    Output Parameter:
6228b5c3584SJakub Kruzik .  Ai - ith matrix in composite
6238b5c3584SJakub Kruzik 
6248b5c3584SJakub Kruzik    Level: advanced
6258b5c3584SJakub Kruzik 
6266d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNumberMat(), MatCompositeAddMat(), MATCOMPOSITE
6278b5c3584SJakub Kruzik 
6288b5c3584SJakub Kruzik @*/
629d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai)
6308b5c3584SJakub Kruzik {
631d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
6328b5c3584SJakub Kruzik 
6338b5c3584SJakub Kruzik   PetscFunctionBegin;
634d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
635d7f81bf2SJakub Kruzik   PetscValidLogicalCollectiveInt(mat,i,2);
6368b5c3584SJakub Kruzik   PetscValidPointer(Ai,3);
637d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr);
6388b5c3584SJakub Kruzik   PetscFunctionReturn(0);
6398b5c3584SJakub Kruzik }
6408b5c3584SJakub Kruzik 
64104d534ceSJakub Kruzik static PetscErrorCode MatCompositeSetMergeFromRight_Composite(Mat mat,PetscBool flg)
64204d534ceSJakub Kruzik {
64304d534ceSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
64404d534ceSJakub Kruzik 
64504d534ceSJakub Kruzik   PetscFunctionBegin;
64604d534ceSJakub Kruzik   shell->mergefromright = flg;
64704d534ceSJakub Kruzik   PetscFunctionReturn(0);
64804d534ceSJakub Kruzik }
64904d534ceSJakub Kruzik 
65004d534ceSJakub Kruzik /*@
65104d534ceSJakub Kruzik    MatCompositeSetMergeFromRight - Sets MatCompositeMerge() to start from right.
65204d534ceSJakub Kruzik 
65304d534ceSJakub Kruzik    Logically Collective on Mat
65404d534ceSJakub Kruzik 
65504d534ceSJakub Kruzik    Input Parameter:
65604d534ceSJakub Kruzik +  mat - the composite matrix
65704d534ceSJakub Kruzik -  flg - if true (default) the merge starts with the first added matrix (mat[0])
65804d534ceSJakub Kruzik 
65904d534ceSJakub Kruzik    Level: advanced
66004d534ceSJakub Kruzik 
6618bd739bdSJakub Kruzik    Notes:
6628bd739bdSJakub Kruzik     Has an effect only if the composite matrix is multiplicative.
6638bd739bdSJakub Kruzik 
6648bd739bdSJakub Kruzik     The resulting matrix is the same regardles of the flg. Only the order of operation is changed.
6658bd739bdSJakub Kruzik     If flg is true the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0])))
6668bd739bdSJakub Kruzik     otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0].
6678bd739bdSJakub Kruzik 
6688bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE
66904d534ceSJakub Kruzik 
67004d534ceSJakub Kruzik @*/
67104d534ceSJakub Kruzik PetscErrorCode MatCompositeSetMergeFromRight(Mat mat,PetscBool flg)
67204d534ceSJakub Kruzik {
67304d534ceSJakub Kruzik   PetscErrorCode ierr;
67404d534ceSJakub Kruzik 
67504d534ceSJakub Kruzik   PetscFunctionBegin;
67604d534ceSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
67704d534ceSJakub Kruzik   PetscValidLogicalCollectiveBool(mat,flg,2);
67804d534ceSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetMergeFromRight_C",(Mat,PetscBool),(mat,flg));CHKERRQ(ierr);
67904d534ceSJakub Kruzik   PetscFunctionReturn(0);
68004d534ceSJakub Kruzik }
68104d534ceSJakub Kruzik 
68241cd0125SJakub Kruzik static struct _MatOps MatOps_Values = {0,
68341cd0125SJakub Kruzik                                        0,
68441cd0125SJakub Kruzik                                        0,
68541cd0125SJakub Kruzik                                        MatMult_Composite,
6867bf3a71bSJakub Kruzik                                        MatMultAdd_Composite,
68741cd0125SJakub Kruzik                                 /*  5*/ MatMultTranspose_Composite,
6887bf3a71bSJakub Kruzik                                        MatMultTransposeAdd_Composite,
68941cd0125SJakub Kruzik                                        0,
69041cd0125SJakub Kruzik                                        0,
69141cd0125SJakub Kruzik                                        0,
69241cd0125SJakub Kruzik                                 /* 10*/ 0,
69341cd0125SJakub Kruzik                                        0,
69441cd0125SJakub Kruzik                                        0,
69541cd0125SJakub Kruzik                                        0,
69641cd0125SJakub Kruzik                                        0,
69741cd0125SJakub Kruzik                                 /* 15*/ 0,
69841cd0125SJakub Kruzik                                        0,
69941cd0125SJakub Kruzik                                        MatGetDiagonal_Composite,
70041cd0125SJakub Kruzik                                        MatDiagonalScale_Composite,
70141cd0125SJakub Kruzik                                        0,
70241cd0125SJakub Kruzik                                 /* 20*/ 0,
70341cd0125SJakub Kruzik                                        MatAssemblyEnd_Composite,
70441cd0125SJakub Kruzik                                        0,
70541cd0125SJakub Kruzik                                        0,
70641cd0125SJakub Kruzik                                /* 24*/ 0,
70741cd0125SJakub Kruzik                                        0,
70841cd0125SJakub Kruzik                                        0,
70941cd0125SJakub Kruzik                                        0,
71041cd0125SJakub Kruzik                                        0,
71141cd0125SJakub Kruzik                                /* 29*/ 0,
71241cd0125SJakub Kruzik                                        0,
71341cd0125SJakub Kruzik                                        0,
71441cd0125SJakub Kruzik                                        0,
71541cd0125SJakub Kruzik                                        0,
71641cd0125SJakub Kruzik                                /* 34*/ 0,
71741cd0125SJakub Kruzik                                        0,
71841cd0125SJakub Kruzik                                        0,
71941cd0125SJakub Kruzik                                        0,
72041cd0125SJakub Kruzik                                        0,
72141cd0125SJakub Kruzik                                /* 39*/ 0,
72241cd0125SJakub Kruzik                                        0,
72341cd0125SJakub Kruzik                                        0,
72441cd0125SJakub Kruzik                                        0,
72541cd0125SJakub Kruzik                                        0,
72641cd0125SJakub Kruzik                                /* 44*/ 0,
72741cd0125SJakub Kruzik                                        MatScale_Composite,
72841cd0125SJakub Kruzik                                        MatShift_Basic,
72941cd0125SJakub Kruzik                                        0,
73041cd0125SJakub Kruzik                                        0,
73141cd0125SJakub Kruzik                                /* 49*/ 0,
73241cd0125SJakub Kruzik                                        0,
73341cd0125SJakub Kruzik                                        0,
73441cd0125SJakub Kruzik                                        0,
73541cd0125SJakub Kruzik                                        0,
73641cd0125SJakub Kruzik                                /* 54*/ 0,
73741cd0125SJakub Kruzik                                        0,
73841cd0125SJakub Kruzik                                        0,
73941cd0125SJakub Kruzik                                        0,
74041cd0125SJakub Kruzik                                        0,
74141cd0125SJakub Kruzik                                /* 59*/ 0,
74241cd0125SJakub Kruzik                                        MatDestroy_Composite,
74341cd0125SJakub Kruzik                                        0,
74441cd0125SJakub Kruzik                                        0,
74541cd0125SJakub Kruzik                                        0,
74641cd0125SJakub Kruzik                                /* 64*/ 0,
74741cd0125SJakub Kruzik                                        0,
74841cd0125SJakub Kruzik                                        0,
74941cd0125SJakub Kruzik                                        0,
75041cd0125SJakub Kruzik                                        0,
75141cd0125SJakub Kruzik                                /* 69*/ 0,
75241cd0125SJakub Kruzik                                        0,
75341cd0125SJakub Kruzik                                        0,
75441cd0125SJakub Kruzik                                        0,
75541cd0125SJakub Kruzik                                        0,
75641cd0125SJakub Kruzik                                /* 74*/ 0,
75741cd0125SJakub Kruzik                                        0,
758*4b2558d6SJakub Kruzik                                        MatSetFromOptions_Composite,
75941cd0125SJakub Kruzik                                        0,
76041cd0125SJakub Kruzik                                        0,
76141cd0125SJakub Kruzik                                /* 79*/ 0,
76241cd0125SJakub Kruzik                                        0,
76341cd0125SJakub Kruzik                                        0,
76441cd0125SJakub Kruzik                                        0,
76541cd0125SJakub Kruzik                                        0,
76641cd0125SJakub Kruzik                                /* 84*/ 0,
76741cd0125SJakub Kruzik                                        0,
76841cd0125SJakub Kruzik                                        0,
76941cd0125SJakub Kruzik                                        0,
77041cd0125SJakub Kruzik                                        0,
77141cd0125SJakub Kruzik                                /* 89*/ 0,
77241cd0125SJakub Kruzik                                        0,
77341cd0125SJakub Kruzik                                        0,
77441cd0125SJakub Kruzik                                        0,
77541cd0125SJakub Kruzik                                        0,
77641cd0125SJakub Kruzik                                /* 94*/ 0,
77741cd0125SJakub Kruzik                                        0,
77841cd0125SJakub Kruzik                                        0,
77941cd0125SJakub Kruzik                                        0,
78041cd0125SJakub Kruzik                                        0,
78141cd0125SJakub Kruzik                                 /*99*/ 0,
78241cd0125SJakub Kruzik                                        0,
78341cd0125SJakub Kruzik                                        0,
78441cd0125SJakub Kruzik                                        0,
78541cd0125SJakub Kruzik                                        0,
78641cd0125SJakub Kruzik                                /*104*/ 0,
78741cd0125SJakub Kruzik                                        0,
78841cd0125SJakub Kruzik                                        0,
78941cd0125SJakub Kruzik                                        0,
79041cd0125SJakub Kruzik                                        0,
79141cd0125SJakub Kruzik                                /*109*/ 0,
79241cd0125SJakub Kruzik                                        0,
79341cd0125SJakub Kruzik                                        0,
79441cd0125SJakub Kruzik                                        0,
79541cd0125SJakub Kruzik                                        0,
79641cd0125SJakub Kruzik                                /*114*/ 0,
79741cd0125SJakub Kruzik                                        0,
79841cd0125SJakub Kruzik                                        0,
79941cd0125SJakub Kruzik                                        0,
80041cd0125SJakub Kruzik                                        0,
80141cd0125SJakub Kruzik                                /*119*/ 0,
80241cd0125SJakub Kruzik                                        0,
80341cd0125SJakub Kruzik                                        0,
80441cd0125SJakub Kruzik                                        0,
80541cd0125SJakub Kruzik                                        0,
80641cd0125SJakub Kruzik                                /*124*/ 0,
80741cd0125SJakub Kruzik                                        0,
80841cd0125SJakub Kruzik                                        0,
80941cd0125SJakub Kruzik                                        0,
81041cd0125SJakub Kruzik                                        0,
81141cd0125SJakub Kruzik                                /*129*/ 0,
81241cd0125SJakub Kruzik                                        0,
81341cd0125SJakub Kruzik                                        0,
81441cd0125SJakub Kruzik                                        0,
81541cd0125SJakub Kruzik                                        0,
81641cd0125SJakub Kruzik                                /*134*/ 0,
81741cd0125SJakub Kruzik                                        0,
81841cd0125SJakub Kruzik                                        0,
81941cd0125SJakub Kruzik                                        0,
82041cd0125SJakub Kruzik                                        0,
82141cd0125SJakub Kruzik                                /*139*/ 0,
82241cd0125SJakub Kruzik                                        0,
82341cd0125SJakub Kruzik                                        0
82441cd0125SJakub Kruzik };
82541cd0125SJakub Kruzik 
82641cd0125SJakub Kruzik /*MC
82741cd0125SJakub Kruzik    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices.
82841cd0125SJakub Kruzik     The matrices need to have a correct size and parallel layout for the sum or product to be valid.
82941cd0125SJakub Kruzik 
83041cd0125SJakub Kruzik    Notes:
83141cd0125SJakub Kruzik     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
83241cd0125SJakub Kruzik 
83341cd0125SJakub Kruzik   Level: advanced
83441cd0125SJakub Kruzik 
8356d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeMerge(), MatCompositeSetMergeFromRight(), MatCompositeGetNumberMat(), MatCompositeGetMat()
83641cd0125SJakub Kruzik M*/
83741cd0125SJakub Kruzik 
83841cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A)
83941cd0125SJakub Kruzik {
84041cd0125SJakub Kruzik   Mat_Composite  *b;
84141cd0125SJakub Kruzik   PetscErrorCode ierr;
84241cd0125SJakub Kruzik 
84341cd0125SJakub Kruzik   PetscFunctionBegin;
84441cd0125SJakub Kruzik   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
84541cd0125SJakub Kruzik   A->data = (void*)b;
84641cd0125SJakub Kruzik   ierr    = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
84741cd0125SJakub Kruzik 
84841cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
84941cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
85041cd0125SJakub Kruzik 
85141cd0125SJakub Kruzik   A->assembled      = PETSC_TRUE;
85241cd0125SJakub Kruzik   A->preallocated   = PETSC_TRUE;
85341cd0125SJakub Kruzik   b->type           = MAT_COMPOSITE_ADDITIVE;
85441cd0125SJakub Kruzik   b->scale          = 1.0;
85541cd0125SJakub Kruzik   b->nmat           = 0;
856*4b2558d6SJakub Kruzik   b->merge          = PETSC_FALSE;
85704d534ceSJakub Kruzik   b->mergefromright = PETSC_TRUE;
85841cd0125SJakub Kruzik 
85941cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr);
86041cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr);
8616dbc55e5SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr);
86241cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr);
8636d0add67SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNumberMat_C",MatCompositeGetNumberMat_Composite);CHKERRQ(ierr);
86441cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr);
86504d534ceSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeFromRight_C",MatCompositeSetMergeFromRight_Composite);CHKERRQ(ierr);
86641cd0125SJakub Kruzik 
86741cd0125SJakub Kruzik   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
86841cd0125SJakub Kruzik   PetscFunctionReturn(0);
86941cd0125SJakub Kruzik }
87041cd0125SJakub Kruzik 
871