xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 7c4f633dc6bb6149cca88d301ead35a99e103cbb)
1793850ffSBarry Smith #define PETSCMAT_DLL
2793850ffSBarry Smith 
3*7c4f633dSBarry Smith #include "private/matimpl.h"        /*I "petscmat.h" I*/
4793850ffSBarry Smith 
5793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink;
6793850ffSBarry Smith struct _Mat_CompositeLink {
7793850ffSBarry Smith   Mat               mat;
86d7c1e57SBarry Smith   Vec               work;
96d7c1e57SBarry Smith   Mat_CompositeLink next,prev;
10793850ffSBarry Smith };
11793850ffSBarry Smith 
12793850ffSBarry Smith typedef struct {
136d7c1e57SBarry Smith   MatCompositeType  type;
146d7c1e57SBarry Smith   Mat_CompositeLink head,tail;
15793850ffSBarry Smith   Vec               work;
16793850ffSBarry Smith } Mat_Composite;
17793850ffSBarry Smith 
18793850ffSBarry Smith #undef __FUNCT__
19793850ffSBarry Smith #define __FUNCT__ "MatDestroy_Composite"
20793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
21793850ffSBarry Smith {
22793850ffSBarry Smith   PetscErrorCode   ierr;
232c33bbaeSSatish Balay   Mat_Composite    *shell = (Mat_Composite*)mat->data;
246d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head,oldnext;
25793850ffSBarry Smith 
26793850ffSBarry Smith   PetscFunctionBegin;
27793850ffSBarry Smith   while (next) {
28793850ffSBarry Smith     ierr = MatDestroy(next->mat);CHKERRQ(ierr);
296d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
306d7c1e57SBarry Smith       ierr = VecDestroy(next->work);CHKERRQ(ierr);
316d7c1e57SBarry Smith     }
326d7c1e57SBarry Smith     oldnext = next;
33793850ffSBarry Smith     next     = next->next;
346d7c1e57SBarry Smith     ierr     = PetscFree(oldnext);CHKERRQ(ierr);
35793850ffSBarry Smith   }
36793850ffSBarry Smith   if (shell->work) {ierr = VecDestroy(shell->work);CHKERRQ(ierr);}
37793850ffSBarry Smith   ierr      = PetscFree(shell);CHKERRQ(ierr);
38793850ffSBarry Smith   mat->data = 0;
39793850ffSBarry Smith   PetscFunctionReturn(0);
40793850ffSBarry Smith }
41793850ffSBarry Smith 
42793850ffSBarry Smith #undef __FUNCT__
436d7c1e57SBarry Smith #define __FUNCT__ "MatMult_Composite_Multiplicative"
446d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
456d7c1e57SBarry Smith {
466d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
476d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head;
486d7c1e57SBarry Smith   PetscErrorCode    ierr;
496d7c1e57SBarry Smith   Vec               in,out;
506d7c1e57SBarry Smith 
516d7c1e57SBarry Smith   PetscFunctionBegin;
526d7c1e57SBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
536d7c1e57SBarry Smith   in = x;
546d7c1e57SBarry Smith   while (next->next) {
556d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
566d7c1e57SBarry Smith       ierr = MatGetVecs(next->mat,PETSC_NULL,&next->work);CHKERRQ(ierr);
576d7c1e57SBarry Smith     }
586d7c1e57SBarry Smith     out = next->work;
596d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
606d7c1e57SBarry Smith     in   = out;
616d7c1e57SBarry Smith     next = next->next;
626d7c1e57SBarry Smith   }
636d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
646d7c1e57SBarry Smith   PetscFunctionReturn(0);
656d7c1e57SBarry Smith }
666d7c1e57SBarry Smith 
676d7c1e57SBarry Smith #undef __FUNCT__
686d7c1e57SBarry Smith #define __FUNCT__ "MatMultTranspose_Composite_Multiplicative"
696d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
706d7c1e57SBarry Smith {
716d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
726d7c1e57SBarry Smith   Mat_CompositeLink tail = shell->tail;
736d7c1e57SBarry Smith   PetscErrorCode    ierr;
746d7c1e57SBarry Smith   Vec               in,out;
756d7c1e57SBarry Smith 
766d7c1e57SBarry Smith   PetscFunctionBegin;
776d7c1e57SBarry Smith   if (!tail) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
786d7c1e57SBarry Smith   in = x;
796d7c1e57SBarry Smith   while (tail->prev) {
806d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
816d7c1e57SBarry Smith       ierr = MatGetVecs(tail->mat,PETSC_NULL,&tail->prev->work);CHKERRQ(ierr);
826d7c1e57SBarry Smith     }
836d7c1e57SBarry Smith     out = tail->prev->work;
846d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
856d7c1e57SBarry Smith     in   = out;
866d7c1e57SBarry Smith     tail = tail->prev;
876d7c1e57SBarry Smith   }
886d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
896d7c1e57SBarry Smith   PetscFunctionReturn(0);
906d7c1e57SBarry Smith }
916d7c1e57SBarry Smith 
926d7c1e57SBarry Smith #undef __FUNCT__
93793850ffSBarry Smith #define __FUNCT__ "MatMult_Composite"
94793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
95793850ffSBarry Smith {
96793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
97793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
98793850ffSBarry Smith   PetscErrorCode    ierr;
99793850ffSBarry Smith 
100793850ffSBarry Smith   PetscFunctionBegin;
101793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
102793850ffSBarry Smith   ierr = MatMult(next->mat,x,y);CHKERRQ(ierr);
103793850ffSBarry Smith   while ((next = next->next)) {
104793850ffSBarry Smith     ierr = MatMultAdd(next->mat,x,y,y);CHKERRQ(ierr);
105793850ffSBarry Smith   }
106793850ffSBarry Smith   PetscFunctionReturn(0);
107793850ffSBarry Smith }
108793850ffSBarry Smith 
109793850ffSBarry Smith #undef __FUNCT__
110793850ffSBarry Smith #define __FUNCT__ "MatMultTranspose_Composite"
111793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
112793850ffSBarry Smith {
113793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
114793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
115793850ffSBarry Smith   PetscErrorCode    ierr;
116793850ffSBarry Smith 
117793850ffSBarry Smith   PetscFunctionBegin;
118793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
119793850ffSBarry Smith   ierr = MatMultTranspose(next->mat,x,y);CHKERRQ(ierr);
120793850ffSBarry Smith   while ((next = next->next)) {
121793850ffSBarry Smith     ierr = MatMultTransposeAdd(next->mat,x,y,y);CHKERRQ(ierr);
122793850ffSBarry Smith   }
123793850ffSBarry Smith   PetscFunctionReturn(0);
124793850ffSBarry Smith }
125793850ffSBarry Smith 
126793850ffSBarry Smith #undef __FUNCT__
127793850ffSBarry Smith #define __FUNCT__ "MatGetDiagonal_Composite"
128793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
129793850ffSBarry Smith {
130793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
131793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
132793850ffSBarry Smith   PetscErrorCode    ierr;
133793850ffSBarry Smith 
134793850ffSBarry Smith   PetscFunctionBegin;
135793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
136793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
137793850ffSBarry Smith   if (next->next && !shell->work) {
138793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
139793850ffSBarry Smith   }
140793850ffSBarry Smith   while ((next = next->next)) {
141793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
142793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
143793850ffSBarry Smith   }
144793850ffSBarry Smith   PetscFunctionReturn(0);
145793850ffSBarry Smith }
146793850ffSBarry Smith 
147793850ffSBarry Smith #undef __FUNCT__
148793850ffSBarry Smith #define __FUNCT__ "MatAssemblyEnd_Composite"
149793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
150793850ffSBarry Smith {
151b52f573bSBarry Smith   PetscErrorCode ierr;
152b52f573bSBarry Smith   PetscTruth     flg;
153b52f573bSBarry Smith 
154793850ffSBarry Smith   PetscFunctionBegin;
1557adad957SLisandro Dalcin   ierr = PetscOptionsHasName(((PetscObject)Y)->prefix,"-mat_composite_merge",&flg);CHKERRQ(ierr);
156b52f573bSBarry Smith   if (flg) {
157b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
158b52f573bSBarry Smith   }
159793850ffSBarry Smith   PetscFunctionReturn(0);
160793850ffSBarry Smith }
161793850ffSBarry Smith 
162793850ffSBarry Smith 
163793850ffSBarry Smith static struct _MatOps MatOps_Values = {0,
164793850ffSBarry Smith        0,
165793850ffSBarry Smith        0,
166793850ffSBarry Smith        MatMult_Composite,
167793850ffSBarry Smith        0,
168793850ffSBarry Smith /* 5*/ MatMultTranspose_Composite,
169793850ffSBarry Smith        0,
170793850ffSBarry Smith        0,
171793850ffSBarry Smith        0,
172793850ffSBarry Smith        0,
173793850ffSBarry Smith /*10*/ 0,
174793850ffSBarry Smith        0,
175793850ffSBarry Smith        0,
176793850ffSBarry Smith        0,
177793850ffSBarry Smith        0,
178793850ffSBarry Smith /*15*/ 0,
179793850ffSBarry Smith        0,
180793850ffSBarry Smith        MatGetDiagonal_Composite,
181793850ffSBarry Smith        0,
182793850ffSBarry Smith        0,
183793850ffSBarry Smith /*20*/ 0,
184793850ffSBarry Smith        MatAssemblyEnd_Composite,
185793850ffSBarry Smith        0,
186793850ffSBarry Smith        0,
187793850ffSBarry Smith        0,
188793850ffSBarry Smith /*25*/ 0,
189793850ffSBarry Smith        0,
190793850ffSBarry Smith        0,
191793850ffSBarry Smith        0,
192793850ffSBarry Smith        0,
193793850ffSBarry Smith /*30*/ 0,
194793850ffSBarry Smith        0,
195793850ffSBarry Smith        0,
196793850ffSBarry Smith        0,
197793850ffSBarry Smith        0,
198793850ffSBarry Smith /*35*/ 0,
199793850ffSBarry Smith        0,
200793850ffSBarry Smith        0,
201793850ffSBarry Smith        0,
202793850ffSBarry Smith        0,
203793850ffSBarry Smith /*40*/ 0,
204793850ffSBarry Smith        0,
205793850ffSBarry Smith        0,
206793850ffSBarry Smith        0,
207793850ffSBarry Smith        0,
208793850ffSBarry Smith /*45*/ 0,
209793850ffSBarry Smith        0,
210793850ffSBarry Smith        0,
211793850ffSBarry Smith        0,
212793850ffSBarry Smith        0,
213793850ffSBarry Smith /*50*/ 0,
214793850ffSBarry Smith        0,
215793850ffSBarry Smith        0,
216793850ffSBarry Smith        0,
217793850ffSBarry Smith        0,
218793850ffSBarry Smith /*55*/ 0,
219793850ffSBarry Smith        0,
220793850ffSBarry Smith        0,
221793850ffSBarry Smith        0,
222793850ffSBarry Smith        0,
223793850ffSBarry Smith /*60*/ 0,
224793850ffSBarry Smith        MatDestroy_Composite,
225793850ffSBarry Smith        0,
226793850ffSBarry Smith        0,
227793850ffSBarry Smith        0,
228793850ffSBarry Smith /*65*/ 0,
229793850ffSBarry Smith        0,
230793850ffSBarry Smith        0,
231793850ffSBarry Smith        0,
232793850ffSBarry Smith        0,
233793850ffSBarry Smith /*70*/ 0,
234793850ffSBarry Smith        0,
235793850ffSBarry Smith        0,
236793850ffSBarry Smith        0,
237793850ffSBarry Smith        0,
238793850ffSBarry Smith /*75*/ 0,
239793850ffSBarry Smith        0,
240793850ffSBarry Smith        0,
241793850ffSBarry Smith        0,
242793850ffSBarry Smith        0,
243793850ffSBarry Smith /*80*/ 0,
244793850ffSBarry Smith        0,
245793850ffSBarry Smith        0,
246793850ffSBarry Smith        0,
247793850ffSBarry Smith        0,
248793850ffSBarry Smith /*85*/ 0,
249793850ffSBarry Smith        0,
250793850ffSBarry Smith        0,
251793850ffSBarry Smith        0,
252793850ffSBarry Smith        0,
253793850ffSBarry Smith /*90*/ 0,
254793850ffSBarry Smith        0,
255793850ffSBarry Smith        0,
256793850ffSBarry Smith        0,
257793850ffSBarry Smith        0,
258793850ffSBarry Smith /*95*/ 0,
259793850ffSBarry Smith        0,
260793850ffSBarry Smith        0,
261793850ffSBarry Smith        0};
262793850ffSBarry Smith 
263793850ffSBarry Smith /*MC
2646d7c1e57SBarry Smith    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices (all matrices are of same size and parallel layout).
2656d7c1e57SBarry Smith 
2666d7c1e57SBarry Smith    Notes: to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
267793850ffSBarry Smith 
268793850ffSBarry Smith   Level: advanced
269793850ffSBarry Smith 
2706d7c1e57SBarry Smith .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType
271793850ffSBarry Smith M*/
272793850ffSBarry Smith 
273793850ffSBarry Smith EXTERN_C_BEGIN
274793850ffSBarry Smith #undef __FUNCT__
275793850ffSBarry Smith #define __FUNCT__ "MatCreate_Composite"
276793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Composite(Mat A)
277793850ffSBarry Smith {
278793850ffSBarry Smith   Mat_Composite  *b;
279793850ffSBarry Smith   PetscErrorCode ierr;
280793850ffSBarry Smith 
281793850ffSBarry Smith   PetscFunctionBegin;
28238f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_Composite,&b);CHKERRQ(ierr);
283793850ffSBarry Smith   A->data = (void*)b;
28438f2d2fdSLisandro Dalcin   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
285793850ffSBarry Smith 
286d0f46423SBarry Smith   ierr = PetscMapSetBlockSize(A->rmap,1);CHKERRQ(ierr);
287d0f46423SBarry Smith   ierr = PetscMapSetBlockSize(A->cmap,1);CHKERRQ(ierr);
288d0f46423SBarry Smith   ierr = PetscMapSetUp(A->rmap);CHKERRQ(ierr);
289d0f46423SBarry Smith   ierr = PetscMapSetUp(A->cmap);CHKERRQ(ierr);
290793850ffSBarry Smith 
291793850ffSBarry Smith   A->assembled     = PETSC_TRUE;
292793850ffSBarry Smith   A->preallocated  = PETSC_FALSE;
2936d7c1e57SBarry Smith   b->type          = MAT_COMPOSITE_ADDITIVE;
294793850ffSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
295793850ffSBarry Smith   PetscFunctionReturn(0);
296793850ffSBarry Smith }
297793850ffSBarry Smith EXTERN_C_END
298793850ffSBarry Smith 
299793850ffSBarry Smith #undef __FUNCT__
300793850ffSBarry Smith #define __FUNCT__ "MatCreateComposite"
301793850ffSBarry Smith /*@C
302793850ffSBarry Smith    MatCreateComposite - Creates a matrix as the sum of zero or more matrices
303793850ffSBarry Smith 
304793850ffSBarry Smith   Collective on MPI_Comm
305793850ffSBarry Smith 
306793850ffSBarry Smith    Input Parameters:
307793850ffSBarry Smith +  comm - MPI communicator
308793850ffSBarry Smith .  nmat - number of matrices to put in
309793850ffSBarry Smith -  mats - the matrices
310793850ffSBarry Smith 
311793850ffSBarry Smith    Output Parameter:
312793850ffSBarry Smith .  A - the matrix
313793850ffSBarry Smith 
314793850ffSBarry Smith    Level: advanced
315793850ffSBarry Smith 
316793850ffSBarry Smith    Notes:
317793850ffSBarry Smith      Alternative construction
318793850ffSBarry Smith $       MatCreate(comm,&mat);
319793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
320793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
321793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
322793850ffSBarry Smith $       ....
323793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
324b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
325b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
326793850ffSBarry Smith 
3276d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
3286d7c1e57SBarry Smith 
3296d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType
330793850ffSBarry Smith 
331793850ffSBarry Smith @*/
332793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
333793850ffSBarry Smith {
334793850ffSBarry Smith   PetscErrorCode ierr;
335793850ffSBarry Smith   PetscInt       m,n,M,N,i;
336793850ffSBarry Smith 
337793850ffSBarry Smith   PetscFunctionBegin;
338793850ffSBarry Smith   if (nmat < 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
339f3f84630SBarry Smith   PetscValidPointer(mat,3);
340793850ffSBarry Smith 
341793850ffSBarry Smith   ierr = MatGetLocalSize(mats[0],&m,&n);CHKERRQ(ierr);
342793850ffSBarry Smith   ierr = MatGetSize(mats[0],&M,&N);CHKERRQ(ierr);
343793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
344793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
345793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
346793850ffSBarry Smith   for (i=0; i<nmat; i++) {
347793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
348793850ffSBarry Smith   }
349b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
350b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
351793850ffSBarry Smith   PetscFunctionReturn(0);
352793850ffSBarry Smith }
353793850ffSBarry Smith 
354793850ffSBarry Smith #undef __FUNCT__
355793850ffSBarry Smith #define __FUNCT__ "MatCompositeAddMat"
356793850ffSBarry Smith /*@
357793850ffSBarry Smith     MatCompositeAddMat - add another matrix to a composite matrix
358793850ffSBarry Smith 
359793850ffSBarry Smith    Collective on Mat
360793850ffSBarry Smith 
361793850ffSBarry Smith     Input Parameters:
362793850ffSBarry Smith +   mat - the composite matrix
363793850ffSBarry Smith -   smat - the partial matrix
364793850ffSBarry Smith 
365793850ffSBarry Smith    Level: advanced
366793850ffSBarry Smith 
367793850ffSBarry Smith .seealso: MatCreateComposite()
368793850ffSBarry Smith @*/
369793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeAddMat(Mat mat,Mat smat)
370793850ffSBarry Smith {
37138f2d2fdSLisandro Dalcin   Mat_Composite     *shell;
372793850ffSBarry Smith   PetscErrorCode    ierr;
373793850ffSBarry Smith   Mat_CompositeLink ilink,next;
374793850ffSBarry Smith 
375793850ffSBarry Smith   PetscFunctionBegin;
376793850ffSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
377793850ffSBarry Smith   PetscValidHeaderSpecific(smat,MAT_COOKIE,2);
37838f2d2fdSLisandro Dalcin   ierr        = PetscNewLog(mat,struct _Mat_CompositeLink,&ilink);CHKERRQ(ierr);
379793850ffSBarry Smith   ilink->next = 0;
380793850ffSBarry Smith   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
381c3122656SLisandro Dalcin   ilink->mat  = smat;
382793850ffSBarry Smith 
38338f2d2fdSLisandro Dalcin   shell = (Mat_Composite*)mat->data;
384793850ffSBarry Smith   next = shell->head;
385793850ffSBarry Smith   if (!next) {
386793850ffSBarry Smith     shell->head  = ilink;
387793850ffSBarry Smith   } else {
388793850ffSBarry Smith     while (next->next) {
389793850ffSBarry Smith       next = next->next;
390793850ffSBarry Smith     }
391793850ffSBarry Smith     next->next      = ilink;
3926d7c1e57SBarry Smith     ilink->prev     = next;
3936d7c1e57SBarry Smith   }
3946d7c1e57SBarry Smith   shell->tail = ilink;
3956d7c1e57SBarry Smith   PetscFunctionReturn(0);
3966d7c1e57SBarry Smith }
3976d7c1e57SBarry Smith 
3986d7c1e57SBarry Smith #undef __FUNCT__
3996d7c1e57SBarry Smith #define __FUNCT__ "MatCompositeSetType"
4006d7c1e57SBarry Smith /*@C
4016d7c1e57SBarry Smith    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product
4026d7c1e57SBarry Smith 
4036d7c1e57SBarry Smith   Collective on MPI_Comm
4046d7c1e57SBarry Smith 
4056d7c1e57SBarry Smith    Input Parameters:
4066d7c1e57SBarry Smith .  mat - the composite matrix
4076d7c1e57SBarry Smith 
4086d7c1e57SBarry Smith 
4096d7c1e57SBarry Smith    Level: advanced
4106d7c1e57SBarry Smith 
4116d7c1e57SBarry Smith    Notes:
4126d7c1e57SBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
4136d7c1e57SBarry Smith     matrix in the composite matrix.
4146d7c1e57SBarry Smith 
4156d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
4166d7c1e57SBarry Smith 
4176d7c1e57SBarry Smith @*/
4186d7c1e57SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeSetType(Mat mat,MatCompositeType type)
4196d7c1e57SBarry Smith {
4206d7c1e57SBarry Smith   Mat_Composite  *b = (Mat_Composite*)mat->data;
4216d7c1e57SBarry Smith   PetscTruth     flg;
4226d7c1e57SBarry Smith   PetscErrorCode ierr;
4236d7c1e57SBarry Smith 
4246d7c1e57SBarry Smith   PetscFunctionBegin;
4256d7c1e57SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATCOMPOSITE,&flg);CHKERRQ(ierr);
4266d7c1e57SBarry Smith   if (!flg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Can only use with composite matrix");
4276d7c1e57SBarry Smith   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
4286d7c1e57SBarry Smith     mat->ops->getdiagonal   = 0;
4296d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite_Multiplicative;
4306d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
4316d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_MULTIPLICATIVE;
4326d7c1e57SBarry Smith   } else {
4336d7c1e57SBarry Smith     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
4346d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite;
4356d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite;
4366d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_ADDITIVE;
437793850ffSBarry Smith   }
438793850ffSBarry Smith   PetscFunctionReturn(0);
439793850ffSBarry Smith }
440793850ffSBarry Smith 
4416d7c1e57SBarry Smith 
442b52f573bSBarry Smith #undef __FUNCT__
443b52f573bSBarry Smith #define __FUNCT__ "MatCompositeMerge"
444b52f573bSBarry Smith /*@C
445b52f573bSBarry Smith    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
446b52f573bSBarry Smith      by summing all the matrices inside the composite matrix.
447b52f573bSBarry Smith 
448b52f573bSBarry Smith   Collective on MPI_Comm
449b52f573bSBarry Smith 
450b52f573bSBarry Smith    Input Parameters:
451b52f573bSBarry Smith .  mat - the composite matrix
452b52f573bSBarry Smith 
453b52f573bSBarry Smith 
454b52f573bSBarry Smith    Options Database:
455b52f573bSBarry Smith .  -mat_composite_merge  (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked)
456b52f573bSBarry Smith 
457b52f573bSBarry Smith    Level: advanced
458b52f573bSBarry Smith 
459b52f573bSBarry Smith    Notes:
460b52f573bSBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
461b52f573bSBarry Smith     matrix in the composite matrix.
462b52f573bSBarry Smith 
463b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
464b52f573bSBarry Smith 
465b52f573bSBarry Smith @*/
466b52f573bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeMerge(Mat mat)
467b52f573bSBarry Smith {
468b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
4696d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head, prev = shell->tail;
470b52f573bSBarry Smith   PetscErrorCode    ierr;
4716d7c1e57SBarry Smith   Mat               tmat,newmat;
472b52f573bSBarry Smith 
473b52f573bSBarry Smith   PetscFunctionBegin;
474b52f573bSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
475b52f573bSBarry Smith 
476b52f573bSBarry Smith   PetscFunctionBegin;
4776d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
478b52f573bSBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
479b52f573bSBarry Smith     while ((next = next->next)) {
480b52f573bSBarry Smith       ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
481b52f573bSBarry Smith     }
4826d7c1e57SBarry Smith   } else {
4836d7c1e57SBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4846d7c1e57SBarry Smith     while ((prev = prev->prev)) {
4856d7c1e57SBarry Smith       ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
4866d7c1e57SBarry Smith       ierr = MatDestroy(tmat);CHKERRQ(ierr);
4876d7c1e57SBarry Smith       tmat = newmat;
4886d7c1e57SBarry Smith     }
4896d7c1e57SBarry Smith   }
4906d7c1e57SBarry Smith   ierr = MatHeaderReplace(mat,tmat);CHKERRQ(ierr);
491b52f573bSBarry Smith   PetscFunctionReturn(0);
492b52f573bSBarry Smith }
493