xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 6d7c1e57d1104921c49b03c606cb17f598345938)
1793850ffSBarry Smith #define PETSCMAT_DLL
2793850ffSBarry Smith 
3b9147fbbSdalcinl #include "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;
8*6d7c1e57SBarry Smith   Vec               work;
9*6d7c1e57SBarry Smith   Mat_CompositeLink next,prev;
10793850ffSBarry Smith };
11793850ffSBarry Smith 
12793850ffSBarry Smith typedef struct {
13*6d7c1e57SBarry Smith   MatCompositeType  type;
14*6d7c1e57SBarry 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;
24*6d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head,oldnext;
25793850ffSBarry Smith 
26793850ffSBarry Smith   PetscFunctionBegin;
27793850ffSBarry Smith   while (next) {
28793850ffSBarry Smith     ierr = MatDestroy(next->mat);CHKERRQ(ierr);
29*6d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
30*6d7c1e57SBarry Smith       ierr = VecDestroy(next->work);CHKERRQ(ierr);
31*6d7c1e57SBarry Smith     }
32*6d7c1e57SBarry Smith     oldnext = next;
33793850ffSBarry Smith     next     = next->next;
34*6d7c1e57SBarry 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__
43*6d7c1e57SBarry Smith #define __FUNCT__ "MatMult_Composite_Multiplicative"
44*6d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
45*6d7c1e57SBarry Smith {
46*6d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
47*6d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head;
48*6d7c1e57SBarry Smith   PetscErrorCode    ierr;
49*6d7c1e57SBarry Smith   Vec               in,out;
50*6d7c1e57SBarry Smith 
51*6d7c1e57SBarry Smith   PetscFunctionBegin;
52*6d7c1e57SBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
53*6d7c1e57SBarry Smith   in = x;
54*6d7c1e57SBarry Smith   while (next->next) {
55*6d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
56*6d7c1e57SBarry Smith       ierr = MatGetVecs(next->mat,PETSC_NULL,&next->work);CHKERRQ(ierr);
57*6d7c1e57SBarry Smith     }
58*6d7c1e57SBarry Smith     out = next->work;
59*6d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
60*6d7c1e57SBarry Smith     in   = out;
61*6d7c1e57SBarry Smith     next = next->next;
62*6d7c1e57SBarry Smith   }
63*6d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
64*6d7c1e57SBarry Smith   PetscFunctionReturn(0);
65*6d7c1e57SBarry Smith }
66*6d7c1e57SBarry Smith 
67*6d7c1e57SBarry Smith #undef __FUNCT__
68*6d7c1e57SBarry Smith #define __FUNCT__ "MatMultTranspose_Composite_Multiplicative"
69*6d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
70*6d7c1e57SBarry Smith {
71*6d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
72*6d7c1e57SBarry Smith   Mat_CompositeLink tail = shell->tail;
73*6d7c1e57SBarry Smith   PetscErrorCode    ierr;
74*6d7c1e57SBarry Smith   Vec               in,out;
75*6d7c1e57SBarry Smith 
76*6d7c1e57SBarry Smith   PetscFunctionBegin;
77*6d7c1e57SBarry Smith   if (!tail) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
78*6d7c1e57SBarry Smith   in = x;
79*6d7c1e57SBarry Smith   while (tail->prev) {
80*6d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
81*6d7c1e57SBarry Smith       ierr = MatGetVecs(tail->mat,PETSC_NULL,&tail->prev->work);CHKERRQ(ierr);
82*6d7c1e57SBarry Smith     }
83*6d7c1e57SBarry Smith     out = tail->prev->work;
84*6d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
85*6d7c1e57SBarry Smith     in   = out;
86*6d7c1e57SBarry Smith     tail = tail->prev;
87*6d7c1e57SBarry Smith   }
88*6d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
89*6d7c1e57SBarry Smith   PetscFunctionReturn(0);
90*6d7c1e57SBarry Smith }
91*6d7c1e57SBarry Smith 
92*6d7c1e57SBarry 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
264*6d7c1e57SBarry Smith    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices (all matrices are of same size and parallel layout).
265*6d7c1e57SBarry Smith 
266*6d7c1e57SBarry Smith    Notes: to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
267793850ffSBarry Smith 
268793850ffSBarry Smith   Level: advanced
269793850ffSBarry Smith 
270*6d7c1e57SBarry 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;
293*6d7c1e57SBarry 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 
327*6d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
328*6d7c1e57SBarry Smith 
329*6d7c1e57SBarry 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;
392*6d7c1e57SBarry Smith     ilink->prev     = next;
393*6d7c1e57SBarry Smith   }
394*6d7c1e57SBarry Smith   shell->tail = ilink;
395*6d7c1e57SBarry Smith   PetscFunctionReturn(0);
396*6d7c1e57SBarry Smith }
397*6d7c1e57SBarry Smith 
398*6d7c1e57SBarry Smith #undef __FUNCT__
399*6d7c1e57SBarry Smith #define __FUNCT__ "MatCompositeSetType"
400*6d7c1e57SBarry Smith /*@C
401*6d7c1e57SBarry Smith    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product
402*6d7c1e57SBarry Smith 
403*6d7c1e57SBarry Smith   Collective on MPI_Comm
404*6d7c1e57SBarry Smith 
405*6d7c1e57SBarry Smith    Input Parameters:
406*6d7c1e57SBarry Smith .  mat - the composite matrix
407*6d7c1e57SBarry Smith 
408*6d7c1e57SBarry Smith 
409*6d7c1e57SBarry Smith    Level: advanced
410*6d7c1e57SBarry Smith 
411*6d7c1e57SBarry Smith    Notes:
412*6d7c1e57SBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
413*6d7c1e57SBarry Smith     matrix in the composite matrix.
414*6d7c1e57SBarry Smith 
415*6d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
416*6d7c1e57SBarry Smith 
417*6d7c1e57SBarry Smith @*/
418*6d7c1e57SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeSetType(Mat mat,MatCompositeType type)
419*6d7c1e57SBarry Smith {
420*6d7c1e57SBarry Smith   Mat_Composite  *b = (Mat_Composite*)mat->data;
421*6d7c1e57SBarry Smith   PetscTruth     flg;
422*6d7c1e57SBarry Smith   PetscErrorCode ierr;
423*6d7c1e57SBarry Smith 
424*6d7c1e57SBarry Smith   PetscFunctionBegin;
425*6d7c1e57SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATCOMPOSITE,&flg);CHKERRQ(ierr);
426*6d7c1e57SBarry Smith   if (!flg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Can only use with composite matrix");
427*6d7c1e57SBarry Smith   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
428*6d7c1e57SBarry Smith     mat->ops->getdiagonal   = 0;
429*6d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite_Multiplicative;
430*6d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
431*6d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_MULTIPLICATIVE;
432*6d7c1e57SBarry Smith   } else {
433*6d7c1e57SBarry Smith     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
434*6d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite;
435*6d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite;
436*6d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_ADDITIVE;
437793850ffSBarry Smith   }
438793850ffSBarry Smith   PetscFunctionReturn(0);
439793850ffSBarry Smith }
440793850ffSBarry Smith 
441*6d7c1e57SBarry 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;
469*6d7c1e57SBarry Smith   Mat_CompositeLink next = shell->head, prev = shell->tail;
470b52f573bSBarry Smith   PetscErrorCode    ierr;
471*6d7c1e57SBarry 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;
477*6d7c1e57SBarry 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     }
482*6d7c1e57SBarry Smith   } else {
483*6d7c1e57SBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
484*6d7c1e57SBarry Smith     while ((prev = prev->prev)) {
485*6d7c1e57SBarry Smith       ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
486*6d7c1e57SBarry Smith       ierr = MatDestroy(tmat);CHKERRQ(ierr);
487*6d7c1e57SBarry Smith       tmat = newmat;
488*6d7c1e57SBarry Smith     }
489*6d7c1e57SBarry Smith   }
490*6d7c1e57SBarry Smith   ierr = MatHeaderReplace(mat,tmat);CHKERRQ(ierr);
491b52f573bSBarry Smith   PetscFunctionReturn(0);
492b52f573bSBarry Smith }
493