xref: /petsc/src/mat/impls/composite/mcomposite.c (revision b52f573bf7dd30aec2f45ea71ed0f119e1fe824d)
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;
8793850ffSBarry Smith   Mat_CompositeLink next;
9793850ffSBarry Smith };
10793850ffSBarry Smith 
11793850ffSBarry Smith typedef struct {
12793850ffSBarry Smith   Mat_CompositeLink head;
13793850ffSBarry Smith   Vec               work;
14793850ffSBarry Smith } Mat_Composite;
15793850ffSBarry Smith 
16793850ffSBarry Smith #undef __FUNCT__
17793850ffSBarry Smith #define __FUNCT__ "MatDestroy_Composite"
18793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
19793850ffSBarry Smith {
20793850ffSBarry Smith   PetscErrorCode   ierr;
212c33bbaeSSatish Balay   Mat_Composite    *shell = (Mat_Composite*)mat->data;
22793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
23793850ffSBarry Smith 
24793850ffSBarry Smith   PetscFunctionBegin;
25793850ffSBarry Smith   while (next) {
26793850ffSBarry Smith     ierr = MatDestroy(next->mat);CHKERRQ(ierr);
27793850ffSBarry Smith     next = next->next;
28793850ffSBarry Smith   }
29793850ffSBarry Smith   if (shell->work) {ierr = VecDestroy(shell->work);CHKERRQ(ierr);}
30793850ffSBarry Smith   ierr      = PetscFree(shell);CHKERRQ(ierr);
31793850ffSBarry Smith   mat->data = 0;
32793850ffSBarry Smith   PetscFunctionReturn(0);
33793850ffSBarry Smith }
34793850ffSBarry Smith 
35793850ffSBarry Smith #undef __FUNCT__
36793850ffSBarry Smith #define __FUNCT__ "MatMult_Composite"
37793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
38793850ffSBarry Smith {
39793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
40793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
41793850ffSBarry Smith   PetscErrorCode    ierr;
42793850ffSBarry Smith 
43793850ffSBarry Smith   PetscFunctionBegin;
44793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
45793850ffSBarry Smith   ierr = MatMult(next->mat,x,y);CHKERRQ(ierr);
46793850ffSBarry Smith   while ((next = next->next)) {
47793850ffSBarry Smith     ierr = MatMultAdd(next->mat,x,y,y);CHKERRQ(ierr);
48793850ffSBarry Smith   }
49793850ffSBarry Smith   PetscFunctionReturn(0);
50793850ffSBarry Smith }
51793850ffSBarry Smith 
52793850ffSBarry Smith #undef __FUNCT__
53793850ffSBarry Smith #define __FUNCT__ "MatMultTranspose_Composite"
54793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
55793850ffSBarry Smith {
56793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
57793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
58793850ffSBarry Smith   PetscErrorCode    ierr;
59793850ffSBarry Smith 
60793850ffSBarry Smith   PetscFunctionBegin;
61793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
62793850ffSBarry Smith   ierr = MatMultTranspose(next->mat,x,y);CHKERRQ(ierr);
63793850ffSBarry Smith   while ((next = next->next)) {
64793850ffSBarry Smith     ierr = MatMultTransposeAdd(next->mat,x,y,y);CHKERRQ(ierr);
65793850ffSBarry Smith   }
66793850ffSBarry Smith   PetscFunctionReturn(0);
67793850ffSBarry Smith }
68793850ffSBarry Smith 
69793850ffSBarry Smith #undef __FUNCT__
70793850ffSBarry Smith #define __FUNCT__ "MatGetDiagonal_Composite"
71793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
72793850ffSBarry Smith {
73793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
74793850ffSBarry Smith   Mat_CompositeLink next = shell->head;
75793850ffSBarry Smith   PetscErrorCode    ierr;
76793850ffSBarry Smith 
77793850ffSBarry Smith   PetscFunctionBegin;
78793850ffSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
79793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
80793850ffSBarry Smith   if (next->next && !shell->work) {
81793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
82793850ffSBarry Smith   }
83793850ffSBarry Smith   while ((next = next->next)) {
84793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
85793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
86793850ffSBarry Smith   }
87793850ffSBarry Smith   PetscFunctionReturn(0);
88793850ffSBarry Smith }
89793850ffSBarry Smith 
90793850ffSBarry Smith #undef __FUNCT__
91793850ffSBarry Smith #define __FUNCT__ "MatAssemblyEnd_Composite"
92793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
93793850ffSBarry Smith {
94*b52f573bSBarry Smith   PetscErrorCode ierr;
95*b52f573bSBarry Smith   PetscTruth     flg;
96*b52f573bSBarry Smith 
97793850ffSBarry Smith   PetscFunctionBegin;
98*b52f573bSBarry Smith   ierr = PetscOptionsHasName(Y->prefix,"-mat_composite_merge",&flg);CHKERRQ(ierr);
99*b52f573bSBarry Smith   if (flg) {
100*b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
101*b52f573bSBarry Smith   }
102793850ffSBarry Smith   PetscFunctionReturn(0);
103793850ffSBarry Smith }
104793850ffSBarry Smith 
105793850ffSBarry Smith 
106793850ffSBarry Smith static struct _MatOps MatOps_Values = {0,
107793850ffSBarry Smith        0,
108793850ffSBarry Smith        0,
109793850ffSBarry Smith        MatMult_Composite,
110793850ffSBarry Smith        0,
111793850ffSBarry Smith /* 5*/ MatMultTranspose_Composite,
112793850ffSBarry Smith        0,
113793850ffSBarry Smith        0,
114793850ffSBarry Smith        0,
115793850ffSBarry Smith        0,
116793850ffSBarry Smith /*10*/ 0,
117793850ffSBarry Smith        0,
118793850ffSBarry Smith        0,
119793850ffSBarry Smith        0,
120793850ffSBarry Smith        0,
121793850ffSBarry Smith /*15*/ 0,
122793850ffSBarry Smith        0,
123793850ffSBarry Smith        MatGetDiagonal_Composite,
124793850ffSBarry Smith        0,
125793850ffSBarry Smith        0,
126793850ffSBarry Smith /*20*/ 0,
127793850ffSBarry Smith        MatAssemblyEnd_Composite,
128793850ffSBarry Smith        0,
129793850ffSBarry Smith        0,
130793850ffSBarry Smith        0,
131793850ffSBarry Smith /*25*/ 0,
132793850ffSBarry Smith        0,
133793850ffSBarry Smith        0,
134793850ffSBarry Smith        0,
135793850ffSBarry Smith        0,
136793850ffSBarry Smith /*30*/ 0,
137793850ffSBarry Smith        0,
138793850ffSBarry Smith        0,
139793850ffSBarry Smith        0,
140793850ffSBarry Smith        0,
141793850ffSBarry Smith /*35*/ 0,
142793850ffSBarry Smith        0,
143793850ffSBarry Smith        0,
144793850ffSBarry Smith        0,
145793850ffSBarry Smith        0,
146793850ffSBarry Smith /*40*/ 0,
147793850ffSBarry Smith        0,
148793850ffSBarry Smith        0,
149793850ffSBarry Smith        0,
150793850ffSBarry Smith        0,
151793850ffSBarry Smith /*45*/ 0,
152793850ffSBarry Smith        0,
153793850ffSBarry Smith        0,
154793850ffSBarry Smith        0,
155793850ffSBarry Smith        0,
156793850ffSBarry Smith /*50*/ 0,
157793850ffSBarry Smith        0,
158793850ffSBarry Smith        0,
159793850ffSBarry Smith        0,
160793850ffSBarry Smith        0,
161793850ffSBarry Smith /*55*/ 0,
162793850ffSBarry Smith        0,
163793850ffSBarry Smith        0,
164793850ffSBarry Smith        0,
165793850ffSBarry Smith        0,
166793850ffSBarry Smith /*60*/ 0,
167793850ffSBarry Smith        MatDestroy_Composite,
168793850ffSBarry Smith        0,
169793850ffSBarry Smith        0,
170793850ffSBarry Smith        0,
171793850ffSBarry Smith /*65*/ 0,
172793850ffSBarry Smith        0,
173793850ffSBarry Smith        0,
174793850ffSBarry Smith        0,
175793850ffSBarry Smith        0,
176793850ffSBarry Smith /*70*/ 0,
177793850ffSBarry Smith        0,
178793850ffSBarry Smith        0,
179793850ffSBarry Smith        0,
180793850ffSBarry Smith        0,
181793850ffSBarry Smith /*75*/ 0,
182793850ffSBarry Smith        0,
183793850ffSBarry Smith        0,
184793850ffSBarry Smith        0,
185793850ffSBarry Smith        0,
186793850ffSBarry Smith /*80*/ 0,
187793850ffSBarry Smith        0,
188793850ffSBarry Smith        0,
189793850ffSBarry Smith        0,
190793850ffSBarry Smith        0,
191793850ffSBarry Smith /*85*/ 0,
192793850ffSBarry Smith        0,
193793850ffSBarry Smith        0,
194793850ffSBarry Smith        0,
195793850ffSBarry Smith        0,
196793850ffSBarry Smith /*90*/ 0,
197793850ffSBarry Smith        0,
198793850ffSBarry Smith        0,
199793850ffSBarry Smith        0,
200793850ffSBarry Smith        0,
201793850ffSBarry Smith /*95*/ 0,
202793850ffSBarry Smith        0,
203793850ffSBarry Smith        0,
204793850ffSBarry Smith        0};
205793850ffSBarry Smith 
206793850ffSBarry Smith /*MC
207793850ffSBarry Smith    MATCOMPOSITE - A matrix defined by the sum of one or more matrices (all matrices are of same size and parallel layout)
208793850ffSBarry Smith 
209793850ffSBarry Smith   Level: advanced
210793850ffSBarry Smith 
211*b52f573bSBarry Smith .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeMerge()
212793850ffSBarry Smith M*/
213793850ffSBarry Smith 
214793850ffSBarry Smith EXTERN_C_BEGIN
215793850ffSBarry Smith #undef __FUNCT__
216793850ffSBarry Smith #define __FUNCT__ "MatCreate_Composite"
217793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Composite(Mat A)
218793850ffSBarry Smith {
219793850ffSBarry Smith   Mat_Composite  *b;
220793850ffSBarry Smith   PetscErrorCode ierr;
221793850ffSBarry Smith 
222793850ffSBarry Smith   PetscFunctionBegin;
223793850ffSBarry Smith   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
224793850ffSBarry Smith 
225793850ffSBarry Smith   ierr = PetscNew(Mat_Composite,&b);CHKERRQ(ierr);
226793850ffSBarry Smith   A->data = (void*)b;
227793850ffSBarry Smith 
228793850ffSBarry Smith   ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr);
229793850ffSBarry Smith   ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr);
230793850ffSBarry Smith 
231793850ffSBarry Smith   A->assembled     = PETSC_TRUE;
232793850ffSBarry Smith   A->preallocated  = PETSC_FALSE;
233793850ffSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
234793850ffSBarry Smith   PetscFunctionReturn(0);
235793850ffSBarry Smith }
236793850ffSBarry Smith EXTERN_C_END
237793850ffSBarry Smith 
238793850ffSBarry Smith #undef __FUNCT__
239793850ffSBarry Smith #define __FUNCT__ "MatCreateComposite"
240793850ffSBarry Smith /*@C
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:
251793850ffSBarry Smith .  A - 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]);
263*b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
264*b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
265793850ffSBarry Smith 
266*b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge()
267793850ffSBarry Smith 
268793850ffSBarry Smith @*/
269793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
270793850ffSBarry Smith {
271793850ffSBarry Smith   PetscErrorCode ierr;
272793850ffSBarry Smith   PetscInt       m,n,M,N,i;
273793850ffSBarry Smith 
274793850ffSBarry Smith   PetscFunctionBegin;
275793850ffSBarry Smith   if (nmat < 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
276f3f84630SBarry Smith   PetscValidPointer(mat,3);
277793850ffSBarry Smith 
278793850ffSBarry Smith   ierr = MatGetLocalSize(mats[0],&m,&n);CHKERRQ(ierr);
279793850ffSBarry Smith   ierr = MatGetSize(mats[0],&M,&N);CHKERRQ(ierr);
280793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
281793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
282793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
283793850ffSBarry Smith   for (i=0; i<nmat; i++) {
284793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
285793850ffSBarry Smith   }
286*b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
287*b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
288793850ffSBarry Smith   PetscFunctionReturn(0);
289793850ffSBarry Smith }
290793850ffSBarry Smith 
291793850ffSBarry Smith #undef __FUNCT__
292793850ffSBarry Smith #define __FUNCT__ "MatCompositeAddMat"
293793850ffSBarry Smith /*@
294793850ffSBarry Smith     MatCompositeAddMat - add another matrix to a composite matrix
295793850ffSBarry Smith 
296793850ffSBarry Smith    Collective on Mat
297793850ffSBarry Smith 
298793850ffSBarry Smith     Input Parameters:
299793850ffSBarry Smith +   mat - the composite matrix
300793850ffSBarry Smith -   smat - the partial matrix
301793850ffSBarry Smith 
302793850ffSBarry Smith    Level: advanced
303793850ffSBarry Smith 
304793850ffSBarry Smith .seealso: MatCreateComposite()
305793850ffSBarry Smith @*/
306793850ffSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeAddMat(Mat mat,Mat smat)
307793850ffSBarry Smith {
308793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
309793850ffSBarry Smith   PetscErrorCode    ierr;
310793850ffSBarry Smith   Mat_CompositeLink ilink,next;
311793850ffSBarry Smith 
312793850ffSBarry Smith   PetscFunctionBegin;
313793850ffSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
314793850ffSBarry Smith   PetscValidHeaderSpecific(smat,MAT_COOKIE,2);
315793850ffSBarry Smith   ierr       = PetscNew(struct _Mat_CompositeLink,&ilink);CHKERRQ(ierr);
316793850ffSBarry Smith   ilink->next = 0;
317793850ffSBarry Smith   ilink->mat  = smat;
318793850ffSBarry Smith   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
319793850ffSBarry Smith 
320793850ffSBarry Smith   next = shell->head;
321793850ffSBarry Smith   if (!next) {
322793850ffSBarry Smith     shell->head  = ilink;
323793850ffSBarry Smith   } else {
324793850ffSBarry Smith     while (next->next) {
325793850ffSBarry Smith       next = next->next;
326793850ffSBarry Smith     }
327793850ffSBarry Smith     next->next      = ilink;
328793850ffSBarry Smith   }
329793850ffSBarry Smith   PetscFunctionReturn(0);
330793850ffSBarry Smith }
331793850ffSBarry Smith 
332*b52f573bSBarry Smith #undef __FUNCT__
333*b52f573bSBarry Smith #define __FUNCT__ "MatCompositeMerge"
334*b52f573bSBarry Smith /*@C
335*b52f573bSBarry Smith    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
336*b52f573bSBarry Smith      by summing all the matrices inside the composite matrix.
337*b52f573bSBarry Smith 
338*b52f573bSBarry Smith   Collective on MPI_Comm
339*b52f573bSBarry Smith 
340*b52f573bSBarry Smith    Input Parameters:
341*b52f573bSBarry Smith .  mat - the composite matrix
342*b52f573bSBarry Smith 
343*b52f573bSBarry Smith 
344*b52f573bSBarry Smith    Options Database:
345*b52f573bSBarry Smith .  -mat_composite_merge  (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked)
346*b52f573bSBarry Smith 
347*b52f573bSBarry Smith    Level: advanced
348*b52f573bSBarry Smith 
349*b52f573bSBarry Smith    Notes:
350*b52f573bSBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
351*b52f573bSBarry Smith     matrix in the composite matrix.
352*b52f573bSBarry Smith 
353*b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
354*b52f573bSBarry Smith 
355*b52f573bSBarry Smith @*/
356*b52f573bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCompositeMerge(Mat mat)
357*b52f573bSBarry Smith {
358*b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
359*b52f573bSBarry Smith   Mat_CompositeLink next = shell->head;
360*b52f573bSBarry Smith   PetscErrorCode    ierr;
361*b52f573bSBarry Smith   Mat               tmat;
362*b52f573bSBarry Smith 
363*b52f573bSBarry Smith   PetscFunctionBegin;
364*b52f573bSBarry Smith   if (!next) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
365*b52f573bSBarry Smith 
366*b52f573bSBarry Smith   PetscFunctionBegin;
367*b52f573bSBarry Smith   ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
368*b52f573bSBarry Smith   while ((next = next->next)) {
369*b52f573bSBarry Smith     ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
370*b52f573bSBarry Smith   }
371*b52f573bSBarry Smith   ierr = MatDestroy_Composite(mat);CHKERRQ(ierr);
372*b52f573bSBarry Smith 
373*b52f573bSBarry Smith   ierr = PetscMemcpy(
374*b52f573bSBarry Smith   PetscFunctionReturn(0);
375*b52f573bSBarry Smith }
376