xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 04d534cea0490f06ff1ca11a5e66368ab98e561f)
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*04d534ceSJakub 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 
171793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
172793850ffSBarry Smith {
173793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
174793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
175793850ffSBarry Smith   PetscErrorCode    ierr;
176793850ffSBarry Smith 
177793850ffSBarry Smith   PetscFunctionBegin;
178e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
179e32f2f54SBarry Smith   if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling");
180e4fc5df0SBarry Smith 
181793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
182793850ffSBarry Smith   if (next->next && !shell->work) {
183793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
184793850ffSBarry Smith   }
185793850ffSBarry Smith   while ((next = next->next)) {
186793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
187793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
188793850ffSBarry Smith   }
189e4fc5df0SBarry Smith   ierr = VecScale(v,shell->scale);CHKERRQ(ierr);
190793850ffSBarry Smith   PetscFunctionReturn(0);
191793850ffSBarry Smith }
192793850ffSBarry Smith 
193793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
194793850ffSBarry Smith {
195b52f573bSBarry Smith   PetscErrorCode ierr;
196ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
197b52f573bSBarry Smith 
198793850ffSBarry Smith   PetscFunctionBegin;
199c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)Y)->options,((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr);
200b52f573bSBarry Smith   if (flg) {
201b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
202b52f573bSBarry Smith   }
203793850ffSBarry Smith   PetscFunctionReturn(0);
204793850ffSBarry Smith }
205793850ffSBarry Smith 
206e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha)
207e4fc5df0SBarry Smith {
208e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite*)inA->data;
209e4fc5df0SBarry Smith 
210e4fc5df0SBarry Smith   PetscFunctionBegin;
211321429dbSBarry Smith   a->scale *= alpha;
212e4fc5df0SBarry Smith   PetscFunctionReturn(0);
213e4fc5df0SBarry Smith }
214e4fc5df0SBarry Smith 
215e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right)
216e4fc5df0SBarry Smith {
217e4fc5df0SBarry Smith   Mat_Composite  *a = (Mat_Composite*)inA->data;
218e4fc5df0SBarry Smith   PetscErrorCode ierr;
219e4fc5df0SBarry Smith 
220e4fc5df0SBarry Smith   PetscFunctionBegin;
221e4fc5df0SBarry Smith   if (left) {
222321429dbSBarry Smith     if (!a->left) {
223e4fc5df0SBarry Smith       ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr);
224e4fc5df0SBarry Smith       ierr = VecCopy(left,a->left);CHKERRQ(ierr);
225321429dbSBarry Smith     } else {
226321429dbSBarry Smith       ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr);
227321429dbSBarry Smith     }
228e4fc5df0SBarry Smith   }
229e4fc5df0SBarry Smith   if (right) {
230321429dbSBarry Smith     if (!a->right) {
231e4fc5df0SBarry Smith       ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr);
232e4fc5df0SBarry Smith       ierr = VecCopy(right,a->right);CHKERRQ(ierr);
233321429dbSBarry Smith     } else {
234321429dbSBarry Smith       ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr);
235321429dbSBarry Smith     }
236e4fc5df0SBarry Smith   }
237e4fc5df0SBarry Smith   PetscFunctionReturn(0);
238e4fc5df0SBarry Smith }
239793850ffSBarry Smith 
2402c0821f3SBarry Smith /*@
241793850ffSBarry Smith    MatCreateComposite - Creates a matrix as the sum of zero or more matrices
242793850ffSBarry Smith 
243793850ffSBarry Smith   Collective on MPI_Comm
244793850ffSBarry Smith 
245793850ffSBarry Smith    Input Parameters:
246793850ffSBarry Smith +  comm - MPI communicator
247793850ffSBarry Smith .  nmat - number of matrices to put in
248793850ffSBarry Smith -  mats - the matrices
249793850ffSBarry Smith 
250793850ffSBarry Smith    Output Parameter:
251db36af27SMatthew G. Knepley .  mat - the matrix
252793850ffSBarry Smith 
253793850ffSBarry Smith    Level: advanced
254793850ffSBarry Smith 
255793850ffSBarry Smith    Notes:
256793850ffSBarry Smith      Alternative construction
257793850ffSBarry Smith $       MatCreate(comm,&mat);
258793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
259793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
260793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
261793850ffSBarry Smith $       ....
262793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
263b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
264b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
265793850ffSBarry Smith 
2666d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
2676d7c1e57SBarry Smith 
2686d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType
269793850ffSBarry Smith 
270793850ffSBarry Smith @*/
2717087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
272793850ffSBarry Smith {
273793850ffSBarry Smith   PetscErrorCode ierr;
274793850ffSBarry Smith   PetscInt       m,n,M,N,i;
275793850ffSBarry Smith 
276793850ffSBarry Smith   PetscFunctionBegin;
277e32f2f54SBarry Smith   if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
278f3f84630SBarry Smith   PetscValidPointer(mat,3);
279793850ffSBarry Smith 
280c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr);
281c4f13f43SJakub Kruzik   ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr);
282c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr);
283c4f13f43SJakub Kruzik   ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr);
284793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
285793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
286793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
287793850ffSBarry Smith   for (i=0; i<nmat; i++) {
288793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
289793850ffSBarry Smith   }
290b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
291b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
292793850ffSBarry Smith   PetscFunctionReturn(0);
293793850ffSBarry Smith }
294793850ffSBarry Smith 
295d7f81bf2SJakub Kruzik 
296d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat)
297d7f81bf2SJakub Kruzik {
298d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
299d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink,next = shell->head;
300d7f81bf2SJakub Kruzik   PetscErrorCode    ierr;
301d7f81bf2SJakub Kruzik 
302d7f81bf2SJakub Kruzik   PetscFunctionBegin;
303d7f81bf2SJakub Kruzik   ierr        = PetscNewLog(mat,&ilink);CHKERRQ(ierr);
304d7f81bf2SJakub Kruzik   ilink->next = 0;
305d7f81bf2SJakub Kruzik   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
306d7f81bf2SJakub Kruzik   ilink->mat  = smat;
307d7f81bf2SJakub Kruzik 
308d7f81bf2SJakub Kruzik   if (!next) shell->head = ilink;
309d7f81bf2SJakub Kruzik   else {
310d7f81bf2SJakub Kruzik     while (next->next) {
311d7f81bf2SJakub Kruzik       next = next->next;
312d7f81bf2SJakub Kruzik     }
313d7f81bf2SJakub Kruzik     next->next  = ilink;
314d7f81bf2SJakub Kruzik     ilink->prev = next;
315d7f81bf2SJakub Kruzik   }
316d7f81bf2SJakub Kruzik   shell->tail =  ilink;
317d7f81bf2SJakub Kruzik   shell->nmat += 1;
318d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
319d7f81bf2SJakub Kruzik }
320d7f81bf2SJakub Kruzik 
321793850ffSBarry Smith /*@
322793850ffSBarry Smith     MatCompositeAddMat - add another matrix to a composite matrix
323793850ffSBarry Smith 
324793850ffSBarry Smith    Collective on Mat
325793850ffSBarry Smith 
326793850ffSBarry Smith     Input Parameters:
327793850ffSBarry Smith +   mat - the composite matrix
328793850ffSBarry Smith -   smat - the partial matrix
329793850ffSBarry Smith 
330793850ffSBarry Smith    Level: advanced
331793850ffSBarry Smith 
332793850ffSBarry Smith .seealso: MatCreateComposite()
333793850ffSBarry Smith @*/
3347087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat)
335793850ffSBarry Smith {
336793850ffSBarry Smith   PetscErrorCode    ierr;
337793850ffSBarry Smith 
338793850ffSBarry Smith   PetscFunctionBegin;
3390700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3400700a824SBarry Smith   PetscValidHeaderSpecific(smat,MAT_CLASSID,2);
341d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr);
342d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
343d7f81bf2SJakub Kruzik }
344793850ffSBarry Smith 
345d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type)
346d7f81bf2SJakub Kruzik {
347d7f81bf2SJakub Kruzik   Mat_Composite  *b = (Mat_Composite*)mat->data;
348d7f81bf2SJakub Kruzik 
349d7f81bf2SJakub Kruzik   PetscFunctionBegin;
350d7f81bf2SJakub Kruzik   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
351d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = 0;
352d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite_Multiplicative;
353d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
354d7f81bf2SJakub Kruzik     b->type                 = MAT_COMPOSITE_MULTIPLICATIVE;
355d7f81bf2SJakub Kruzik   } else {
356d7f81bf2SJakub Kruzik     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
357d7f81bf2SJakub Kruzik     mat->ops->mult          = MatMult_Composite;
358d7f81bf2SJakub Kruzik     mat->ops->multtranspose = MatMultTranspose_Composite;
359d7f81bf2SJakub Kruzik     b->type                 = MAT_COMPOSITE_ADDITIVE;
360793850ffSBarry Smith   }
3616d7c1e57SBarry Smith   PetscFunctionReturn(0);
3626d7c1e57SBarry Smith }
3636d7c1e57SBarry Smith 
3642c0821f3SBarry Smith /*@
3656d7c1e57SBarry Smith    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product
3666d7c1e57SBarry Smith 
3676d7c1e57SBarry Smith   Collective on MPI_Comm
3686d7c1e57SBarry Smith 
3696d7c1e57SBarry Smith    Input Parameters:
3706d7c1e57SBarry Smith .  mat - the composite matrix
3716d7c1e57SBarry Smith 
3726d7c1e57SBarry Smith 
3736d7c1e57SBarry Smith    Level: advanced
3746d7c1e57SBarry Smith 
3756d7c1e57SBarry Smith    Notes:
3766d7c1e57SBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
3776d7c1e57SBarry Smith     matrix in the composite matrix.
3786d7c1e57SBarry Smith 
3796d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
3806d7c1e57SBarry Smith 
3816d7c1e57SBarry Smith @*/
3827087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type)
3836d7c1e57SBarry Smith {
3846d7c1e57SBarry Smith   PetscErrorCode ierr;
3856d7c1e57SBarry Smith 
3866d7c1e57SBarry Smith   PetscFunctionBegin;
387d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
388d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr);
389793850ffSBarry Smith   PetscFunctionReturn(0);
390793850ffSBarry Smith }
391793850ffSBarry Smith 
392d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat)
393b52f573bSBarry Smith {
394b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
3956d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head, prev = shell->tail;
396b52f573bSBarry Smith   PetscErrorCode    ierr;
3976d7c1e57SBarry Smith   Mat               tmat,newmat;
3981ba60692SJed Brown   Vec               left,right;
3991ba60692SJed Brown   PetscScalar       scale;
400b52f573bSBarry Smith 
401b52f573bSBarry Smith   PetscFunctionBegin;
402e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
403b52f573bSBarry Smith 
404b52f573bSBarry Smith   PetscFunctionBegin;
4056d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
406b52f573bSBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
407b52f573bSBarry Smith     while ((next = next->next)) {
408b52f573bSBarry Smith       ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
409b52f573bSBarry Smith     }
4106d7c1e57SBarry Smith   } else {
411*04d534ceSJakub Kruzik     if (shell->mergefromright) {
4126d7c1e57SBarry Smith       ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
413b6cfcaf5SJakub Kruzik       while ((next = next->next)) {
414b6cfcaf5SJakub Kruzik         ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
4156bf464f9SBarry Smith         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4166d7c1e57SBarry Smith         tmat = newmat;
4176d7c1e57SBarry Smith       }
418*04d534ceSJakub Kruzik     } else {
419*04d534ceSJakub Kruzik       ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
420*04d534ceSJakub Kruzik       while ((prev = prev->prev)) {
421*04d534ceSJakub Kruzik         ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
422*04d534ceSJakub Kruzik         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
423*04d534ceSJakub Kruzik         tmat = newmat;
424*04d534ceSJakub Kruzik       }
425*04d534ceSJakub Kruzik     }
4266d7c1e57SBarry Smith   }
4271ba60692SJed Brown 
4281ba60692SJed Brown   scale = shell->scale;
4291ba60692SJed Brown   if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);}
4301ba60692SJed Brown   if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);}
4311ba60692SJed Brown 
43228be2f97SBarry Smith   ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr);
4331ba60692SJed Brown 
4341ba60692SJed Brown   ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr);
4351ba60692SJed Brown   ierr = MatScale(mat,scale);CHKERRQ(ierr);
4361ba60692SJed Brown   ierr = VecDestroy(&left);CHKERRQ(ierr);
4371ba60692SJed Brown   ierr = VecDestroy(&right);CHKERRQ(ierr);
438b52f573bSBarry Smith   PetscFunctionReturn(0);
439b52f573bSBarry Smith }
4406a7ede75SJakub Kruzik 
4416a7ede75SJakub Kruzik /*@
442d7f81bf2SJakub Kruzik    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
443d7f81bf2SJakub Kruzik      by summing all the matrices inside the composite matrix.
444d7f81bf2SJakub Kruzik 
445d7f81bf2SJakub Kruzik   Collective on MPI_Comm
446d7f81bf2SJakub Kruzik 
447d7f81bf2SJakub Kruzik    Input Parameters:
448d7f81bf2SJakub Kruzik .  mat - the composite matrix
449d7f81bf2SJakub Kruzik 
450d7f81bf2SJakub Kruzik 
451d7f81bf2SJakub Kruzik    Options Database:
452d7f81bf2SJakub Kruzik .  -mat_composite_merge  (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked)
453d7f81bf2SJakub Kruzik 
454d7f81bf2SJakub Kruzik    Level: advanced
455d7f81bf2SJakub Kruzik 
456d7f81bf2SJakub Kruzik    Notes:
457d7f81bf2SJakub Kruzik       The MatType of the resulting matrix will be the same as the MatType of the FIRST
458d7f81bf2SJakub Kruzik     matrix in the composite matrix.
459d7f81bf2SJakub Kruzik 
460*04d534ceSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMergeFromRight(), MATCOMPOSITE
461d7f81bf2SJakub Kruzik 
462d7f81bf2SJakub Kruzik @*/
463d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat)
464d7f81bf2SJakub Kruzik {
465d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
466d7f81bf2SJakub Kruzik 
467d7f81bf2SJakub Kruzik   PetscFunctionBegin;
468d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
469d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr);
470d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
471d7f81bf2SJakub Kruzik }
472d7f81bf2SJakub Kruzik 
473d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetNMat_Composite(Mat mat,PetscInt *nmat)
474d7f81bf2SJakub Kruzik {
475d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
476d7f81bf2SJakub Kruzik 
477d7f81bf2SJakub Kruzik   PetscFunctionBegin;
478d7f81bf2SJakub Kruzik   *nmat = shell->nmat;
479d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
480d7f81bf2SJakub Kruzik }
481d7f81bf2SJakub Kruzik 
482d7f81bf2SJakub Kruzik /*@
4836a7ede75SJakub Kruzik    MatCompositeGetNMat - Returns the number of matrices in composite.
4846a7ede75SJakub Kruzik 
4856a7ede75SJakub Kruzik    Not Collective
4866a7ede75SJakub Kruzik 
4876a7ede75SJakub Kruzik    Input Parameter:
488d7f81bf2SJakub Kruzik .  mat - the composite matrix
4896a7ede75SJakub Kruzik 
4906a7ede75SJakub Kruzik    Output Parameter:
4916a7ede75SJakub Kruzik .  size - the local size
4926a7ede75SJakub Kruzik .  nmat - number of matrices in composite
4936a7ede75SJakub Kruzik 
4948b5c3584SJakub Kruzik    Level: advanced
4956a7ede75SJakub Kruzik 
4968b5c3584SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat()
4976a7ede75SJakub Kruzik 
4986a7ede75SJakub Kruzik @*/
499d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetNMat(Mat mat,PetscInt *nmat)
5006a7ede75SJakub Kruzik {
501d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
5026a7ede75SJakub Kruzik 
5036a7ede75SJakub Kruzik   PetscFunctionBegin;
504d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5056a7ede75SJakub Kruzik   PetscValidPointer(nmat,2);
506d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetNMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr);
507d7f81bf2SJakub Kruzik   PetscFunctionReturn(0);
508d7f81bf2SJakub Kruzik }
509d7f81bf2SJakub Kruzik 
510d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai)
511d7f81bf2SJakub Kruzik {
512d7f81bf2SJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
513d7f81bf2SJakub Kruzik   Mat_CompositeLink ilink;
514d7f81bf2SJakub Kruzik   PetscInt          k;
515d7f81bf2SJakub Kruzik 
516d7f81bf2SJakub Kruzik   PetscFunctionBegin;
517d7f81bf2SJakub Kruzik   if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat);
518d7f81bf2SJakub Kruzik   ilink = shell->head;
519d7f81bf2SJakub Kruzik   for (k=0; k<i; k++) {
520d7f81bf2SJakub Kruzik     ilink = ilink->next;
521d7f81bf2SJakub Kruzik   }
522d7f81bf2SJakub Kruzik   *Ai = ilink->mat;
5236a7ede75SJakub Kruzik   PetscFunctionReturn(0);
5246a7ede75SJakub Kruzik }
5256a7ede75SJakub Kruzik 
5268b5c3584SJakub Kruzik /*@
5278b5c3584SJakub Kruzik    MatCompositeGetMat - Returns the ith matrix from composite.
5288b5c3584SJakub Kruzik 
5298b5c3584SJakub Kruzik    Logically Collective on Mat
5308b5c3584SJakub Kruzik 
5318b5c3584SJakub Kruzik    Input Parameter:
532d7f81bf2SJakub Kruzik +  mat - the composite matrix
5338b5c3584SJakub Kruzik -  i - the number of requested matrix
5348b5c3584SJakub Kruzik 
5358b5c3584SJakub Kruzik    Output Parameter:
5368b5c3584SJakub Kruzik .  Ai - ith matrix in composite
5378b5c3584SJakub Kruzik 
5388b5c3584SJakub Kruzik    Level: advanced
5398b5c3584SJakub Kruzik 
5408b5c3584SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNMat()
5418b5c3584SJakub Kruzik 
5428b5c3584SJakub Kruzik @*/
543d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai)
5448b5c3584SJakub Kruzik {
545d7f81bf2SJakub Kruzik   PetscErrorCode ierr;
5468b5c3584SJakub Kruzik 
5478b5c3584SJakub Kruzik   PetscFunctionBegin;
548d7f81bf2SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
549d7f81bf2SJakub Kruzik   PetscValidLogicalCollectiveInt(mat,i,2);
5508b5c3584SJakub Kruzik   PetscValidPointer(Ai,3);
551d7f81bf2SJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr);
5528b5c3584SJakub Kruzik   PetscFunctionReturn(0);
5538b5c3584SJakub Kruzik }
5548b5c3584SJakub Kruzik 
555*04d534ceSJakub Kruzik static PetscErrorCode MatCompositeSetMergeFromRight_Composite(Mat mat,PetscBool flg)
556*04d534ceSJakub Kruzik {
557*04d534ceSJakub Kruzik   Mat_Composite     *shell = (Mat_Composite*)mat->data;
558*04d534ceSJakub Kruzik 
559*04d534ceSJakub Kruzik   PetscFunctionBegin;
560*04d534ceSJakub Kruzik   shell->mergefromright = flg;
561*04d534ceSJakub Kruzik   PetscFunctionReturn(0);
562*04d534ceSJakub Kruzik }
563*04d534ceSJakub Kruzik 
564*04d534ceSJakub Kruzik /*@
565*04d534ceSJakub Kruzik    MatCompositeSetMergeFromRight - Sets MatCompositeMerge() to start from right.
566*04d534ceSJakub Kruzik 
567*04d534ceSJakub Kruzik    Logically Collective on Mat
568*04d534ceSJakub Kruzik 
569*04d534ceSJakub Kruzik    Input Parameter:
570*04d534ceSJakub Kruzik +  mat - the composite matrix
571*04d534ceSJakub Kruzik -  flg - if true (default) the merge starts with the first added matrix (mat[0])
572*04d534ceSJakub Kruzik 
573*04d534ceSJakub Kruzik    Level: advanced
574*04d534ceSJakub Kruzik 
575*04d534ceSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge()
576*04d534ceSJakub Kruzik 
577*04d534ceSJakub Kruzik @*/
578*04d534ceSJakub Kruzik PetscErrorCode MatCompositeSetMergeFromRight(Mat mat,PetscBool flg)
579*04d534ceSJakub Kruzik {
580*04d534ceSJakub Kruzik   PetscErrorCode ierr;
581*04d534ceSJakub Kruzik 
582*04d534ceSJakub Kruzik   PetscFunctionBegin;
583*04d534ceSJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
584*04d534ceSJakub Kruzik   PetscValidLogicalCollectiveBool(mat,flg,2);
585*04d534ceSJakub Kruzik   ierr = PetscUseMethod(mat,"MatCompositeSetMergeFromRight_C",(Mat,PetscBool),(mat,flg));CHKERRQ(ierr);
586*04d534ceSJakub Kruzik   PetscFunctionReturn(0);
587*04d534ceSJakub Kruzik }
588*04d534ceSJakub Kruzik 
58941cd0125SJakub Kruzik static struct _MatOps MatOps_Values = {0,
59041cd0125SJakub Kruzik                                        0,
59141cd0125SJakub Kruzik                                        0,
59241cd0125SJakub Kruzik                                        MatMult_Composite,
59341cd0125SJakub Kruzik                                        0,
59441cd0125SJakub Kruzik                                 /*  5*/ MatMultTranspose_Composite,
59541cd0125SJakub Kruzik                                        0,
59641cd0125SJakub Kruzik                                        0,
59741cd0125SJakub Kruzik                                        0,
59841cd0125SJakub Kruzik                                        0,
59941cd0125SJakub Kruzik                                 /* 10*/ 0,
60041cd0125SJakub Kruzik                                        0,
60141cd0125SJakub Kruzik                                        0,
60241cd0125SJakub Kruzik                                        0,
60341cd0125SJakub Kruzik                                        0,
60441cd0125SJakub Kruzik                                 /* 15*/ 0,
60541cd0125SJakub Kruzik                                        0,
60641cd0125SJakub Kruzik                                        MatGetDiagonal_Composite,
60741cd0125SJakub Kruzik                                        MatDiagonalScale_Composite,
60841cd0125SJakub Kruzik                                        0,
60941cd0125SJakub Kruzik                                 /* 20*/ 0,
61041cd0125SJakub Kruzik                                        MatAssemblyEnd_Composite,
61141cd0125SJakub Kruzik                                        0,
61241cd0125SJakub Kruzik                                        0,
61341cd0125SJakub Kruzik                                /* 24*/ 0,
61441cd0125SJakub Kruzik                                        0,
61541cd0125SJakub Kruzik                                        0,
61641cd0125SJakub Kruzik                                        0,
61741cd0125SJakub Kruzik                                        0,
61841cd0125SJakub Kruzik                                /* 29*/ 0,
61941cd0125SJakub Kruzik                                        0,
62041cd0125SJakub Kruzik                                        0,
62141cd0125SJakub Kruzik                                        0,
62241cd0125SJakub Kruzik                                        0,
62341cd0125SJakub Kruzik                                /* 34*/ 0,
62441cd0125SJakub Kruzik                                        0,
62541cd0125SJakub Kruzik                                        0,
62641cd0125SJakub Kruzik                                        0,
62741cd0125SJakub Kruzik                                        0,
62841cd0125SJakub Kruzik                                /* 39*/ 0,
62941cd0125SJakub Kruzik                                        0,
63041cd0125SJakub Kruzik                                        0,
63141cd0125SJakub Kruzik                                        0,
63241cd0125SJakub Kruzik                                        0,
63341cd0125SJakub Kruzik                                /* 44*/ 0,
63441cd0125SJakub Kruzik                                        MatScale_Composite,
63541cd0125SJakub Kruzik                                        MatShift_Basic,
63641cd0125SJakub Kruzik                                        0,
63741cd0125SJakub Kruzik                                        0,
63841cd0125SJakub Kruzik                                /* 49*/ 0,
63941cd0125SJakub Kruzik                                        0,
64041cd0125SJakub Kruzik                                        0,
64141cd0125SJakub Kruzik                                        0,
64241cd0125SJakub Kruzik                                        0,
64341cd0125SJakub Kruzik                                /* 54*/ 0,
64441cd0125SJakub Kruzik                                        0,
64541cd0125SJakub Kruzik                                        0,
64641cd0125SJakub Kruzik                                        0,
64741cd0125SJakub Kruzik                                        0,
64841cd0125SJakub Kruzik                                /* 59*/ 0,
64941cd0125SJakub Kruzik                                        MatDestroy_Composite,
65041cd0125SJakub Kruzik                                        0,
65141cd0125SJakub Kruzik                                        0,
65241cd0125SJakub Kruzik                                        0,
65341cd0125SJakub Kruzik                                /* 64*/ 0,
65441cd0125SJakub Kruzik                                        0,
65541cd0125SJakub Kruzik                                        0,
65641cd0125SJakub Kruzik                                        0,
65741cd0125SJakub Kruzik                                        0,
65841cd0125SJakub Kruzik                                /* 69*/ 0,
65941cd0125SJakub Kruzik                                        0,
66041cd0125SJakub Kruzik                                        0,
66141cd0125SJakub Kruzik                                        0,
66241cd0125SJakub Kruzik                                        0,
66341cd0125SJakub Kruzik                                /* 74*/ 0,
66441cd0125SJakub Kruzik                                        0,
66541cd0125SJakub Kruzik                                        0,
66641cd0125SJakub Kruzik                                        0,
66741cd0125SJakub Kruzik                                        0,
66841cd0125SJakub Kruzik                                /* 79*/ 0,
66941cd0125SJakub Kruzik                                        0,
67041cd0125SJakub Kruzik                                        0,
67141cd0125SJakub Kruzik                                        0,
67241cd0125SJakub Kruzik                                        0,
67341cd0125SJakub Kruzik                                /* 84*/ 0,
67441cd0125SJakub Kruzik                                        0,
67541cd0125SJakub Kruzik                                        0,
67641cd0125SJakub Kruzik                                        0,
67741cd0125SJakub Kruzik                                        0,
67841cd0125SJakub Kruzik                                /* 89*/ 0,
67941cd0125SJakub Kruzik                                        0,
68041cd0125SJakub Kruzik                                        0,
68141cd0125SJakub Kruzik                                        0,
68241cd0125SJakub Kruzik                                        0,
68341cd0125SJakub Kruzik                                /* 94*/ 0,
68441cd0125SJakub Kruzik                                        0,
68541cd0125SJakub Kruzik                                        0,
68641cd0125SJakub Kruzik                                        0,
68741cd0125SJakub Kruzik                                        0,
68841cd0125SJakub Kruzik                                 /*99*/ 0,
68941cd0125SJakub Kruzik                                        0,
69041cd0125SJakub Kruzik                                        0,
69141cd0125SJakub Kruzik                                        0,
69241cd0125SJakub Kruzik                                        0,
69341cd0125SJakub Kruzik                                /*104*/ 0,
69441cd0125SJakub Kruzik                                        0,
69541cd0125SJakub Kruzik                                        0,
69641cd0125SJakub Kruzik                                        0,
69741cd0125SJakub Kruzik                                        0,
69841cd0125SJakub Kruzik                                /*109*/ 0,
69941cd0125SJakub Kruzik                                        0,
70041cd0125SJakub Kruzik                                        0,
70141cd0125SJakub Kruzik                                        0,
70241cd0125SJakub Kruzik                                        0,
70341cd0125SJakub Kruzik                                /*114*/ 0,
70441cd0125SJakub Kruzik                                        0,
70541cd0125SJakub Kruzik                                        0,
70641cd0125SJakub Kruzik                                        0,
70741cd0125SJakub Kruzik                                        0,
70841cd0125SJakub Kruzik                                /*119*/ 0,
70941cd0125SJakub Kruzik                                        0,
71041cd0125SJakub Kruzik                                        0,
71141cd0125SJakub Kruzik                                        0,
71241cd0125SJakub Kruzik                                        0,
71341cd0125SJakub Kruzik                                /*124*/ 0,
71441cd0125SJakub Kruzik                                        0,
71541cd0125SJakub Kruzik                                        0,
71641cd0125SJakub Kruzik                                        0,
71741cd0125SJakub Kruzik                                        0,
71841cd0125SJakub Kruzik                                /*129*/ 0,
71941cd0125SJakub Kruzik                                        0,
72041cd0125SJakub Kruzik                                        0,
72141cd0125SJakub Kruzik                                        0,
72241cd0125SJakub Kruzik                                        0,
72341cd0125SJakub Kruzik                                /*134*/ 0,
72441cd0125SJakub Kruzik                                        0,
72541cd0125SJakub Kruzik                                        0,
72641cd0125SJakub Kruzik                                        0,
72741cd0125SJakub Kruzik                                        0,
72841cd0125SJakub Kruzik                                /*139*/ 0,
72941cd0125SJakub Kruzik                                        0,
73041cd0125SJakub Kruzik                                        0
73141cd0125SJakub Kruzik };
73241cd0125SJakub Kruzik 
73341cd0125SJakub Kruzik /*MC
73441cd0125SJakub Kruzik    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices.
73541cd0125SJakub Kruzik     The matrices need to have a correct size and parallel layout for the sum or product to be valid.
73641cd0125SJakub Kruzik 
73741cd0125SJakub Kruzik    Notes:
73841cd0125SJakub Kruzik     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
73941cd0125SJakub Kruzik 
74041cd0125SJakub Kruzik   Level: advanced
74141cd0125SJakub Kruzik 
742*04d534ceSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeMerge(), MatCompositeSetMergeFromRight(), MatCompositeGetNmat(), MatCompositeGetMat()
74341cd0125SJakub Kruzik M*/
74441cd0125SJakub Kruzik 
74541cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A)
74641cd0125SJakub Kruzik {
74741cd0125SJakub Kruzik   Mat_Composite  *b;
74841cd0125SJakub Kruzik   PetscErrorCode ierr;
74941cd0125SJakub Kruzik 
75041cd0125SJakub Kruzik   PetscFunctionBegin;
75141cd0125SJakub Kruzik   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
75241cd0125SJakub Kruzik   A->data = (void*)b;
75341cd0125SJakub Kruzik   ierr    = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
75441cd0125SJakub Kruzik 
75541cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
75641cd0125SJakub Kruzik   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
75741cd0125SJakub Kruzik 
75841cd0125SJakub Kruzik   A->assembled      = PETSC_TRUE;
75941cd0125SJakub Kruzik   A->preallocated   = PETSC_TRUE;
76041cd0125SJakub Kruzik   b->type           = MAT_COMPOSITE_ADDITIVE;
76141cd0125SJakub Kruzik   b->scale          = 1.0;
76241cd0125SJakub Kruzik   b->nmat           = 0;
763*04d534ceSJakub Kruzik   b->mergefromright = PETSC_TRUE;
76441cd0125SJakub Kruzik 
76541cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr);
76641cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr);
76741cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr);
76841cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNMat_C",MatCompositeGetNMat_Composite);CHKERRQ(ierr);
76941cd0125SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr);
770*04d534ceSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeFromRight_C",MatCompositeSetMergeFromRight_Composite);CHKERRQ(ierr);
77141cd0125SJakub Kruzik 
77241cd0125SJakub Kruzik   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
77341cd0125SJakub Kruzik   PetscFunctionReturn(0);
77441cd0125SJakub Kruzik }
77541cd0125SJakub Kruzik 
776