xref: /petsc/src/mat/impls/composite/mcomposite.c (revision 6a7ede7518fddce1a89d6614aced3be9da5809be)
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;
18*6a7ede75SJakub Kruzik   PetscInt          nmat;
19793850ffSBarry Smith } Mat_Composite;
20793850ffSBarry Smith 
21793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat)
22793850ffSBarry Smith {
23793850ffSBarry Smith   PetscErrorCode    ierr;
242c33bbaeSSatish Balay   Mat_Composite     *shell = (Mat_Composite*)mat->data;
256d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head,oldnext;
26793850ffSBarry Smith 
27793850ffSBarry Smith   PetscFunctionBegin;
28793850ffSBarry Smith   while (next) {
296bf464f9SBarry Smith     ierr = MatDestroy(&next->mat);CHKERRQ(ierr);
306d7c1e57SBarry Smith     if (next->work && (!next->next || next->work != next->next->work)) {
316bf464f9SBarry Smith       ierr = VecDestroy(&next->work);CHKERRQ(ierr);
326d7c1e57SBarry Smith     }
336d7c1e57SBarry Smith     oldnext = next;
34793850ffSBarry Smith     next    = next->next;
356d7c1e57SBarry Smith     ierr    = PetscFree(oldnext);CHKERRQ(ierr);
36793850ffSBarry Smith   }
376bf464f9SBarry Smith   ierr = VecDestroy(&shell->work);CHKERRQ(ierr);
386bf464f9SBarry Smith   ierr = VecDestroy(&shell->left);CHKERRQ(ierr);
396bf464f9SBarry Smith   ierr = VecDestroy(&shell->right);CHKERRQ(ierr);
406bf464f9SBarry Smith   ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr);
416bf464f9SBarry Smith   ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr);
426bf464f9SBarry Smith   ierr = PetscFree(mat->data);CHKERRQ(ierr);
43793850ffSBarry Smith   PetscFunctionReturn(0);
44793850ffSBarry Smith }
45793850ffSBarry Smith 
466d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y)
476d7c1e57SBarry Smith {
486d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
496d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head;
506d7c1e57SBarry Smith   PetscErrorCode    ierr;
516d7c1e57SBarry Smith   Vec               in,out;
526d7c1e57SBarry Smith 
536d7c1e57SBarry Smith   PetscFunctionBegin;
54e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
556d7c1e57SBarry Smith   in = x;
56e4fc5df0SBarry Smith   if (shell->right) {
57e4fc5df0SBarry Smith     if (!shell->rightwork) {
58e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
59e4fc5df0SBarry Smith     }
60e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
61e4fc5df0SBarry Smith     in   = shell->rightwork;
62e4fc5df0SBarry Smith   }
636d7c1e57SBarry Smith   while (next->next) {
646d7c1e57SBarry Smith     if (!next->work) { /* should reuse previous work if the same size */
652a7a6963SBarry Smith       ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr);
666d7c1e57SBarry Smith     }
676d7c1e57SBarry Smith     out  = next->work;
686d7c1e57SBarry Smith     ierr = MatMult(next->mat,in,out);CHKERRQ(ierr);
696d7c1e57SBarry Smith     in   = out;
706d7c1e57SBarry Smith     next = next->next;
716d7c1e57SBarry Smith   }
726d7c1e57SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
73e4fc5df0SBarry Smith   if (shell->left) {
74e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
75e4fc5df0SBarry Smith   }
76e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
776d7c1e57SBarry Smith   PetscFunctionReturn(0);
786d7c1e57SBarry Smith }
796d7c1e57SBarry Smith 
806d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y)
816d7c1e57SBarry Smith {
826d7c1e57SBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
836d7c1e57SBarry Smith   Mat_CompositeLink tail   = shell->tail;
846d7c1e57SBarry Smith   PetscErrorCode    ierr;
856d7c1e57SBarry Smith   Vec               in,out;
866d7c1e57SBarry Smith 
876d7c1e57SBarry Smith   PetscFunctionBegin;
88e32f2f54SBarry Smith   if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
896d7c1e57SBarry Smith   in = x;
90e4fc5df0SBarry Smith   if (shell->left) {
91e4fc5df0SBarry Smith     if (!shell->leftwork) {
92e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
93e4fc5df0SBarry Smith     }
94e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
95e4fc5df0SBarry Smith     in   = shell->leftwork;
96e4fc5df0SBarry Smith   }
976d7c1e57SBarry Smith   while (tail->prev) {
986d7c1e57SBarry Smith     if (!tail->prev->work) { /* should reuse previous work if the same size */
992a7a6963SBarry Smith       ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr);
1006d7c1e57SBarry Smith     }
1016d7c1e57SBarry Smith     out  = tail->prev->work;
1026d7c1e57SBarry Smith     ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr);
1036d7c1e57SBarry Smith     in   = out;
1046d7c1e57SBarry Smith     tail = tail->prev;
1056d7c1e57SBarry Smith   }
1066d7c1e57SBarry Smith   ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr);
107e4fc5df0SBarry Smith   if (shell->right) {
108e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
109e4fc5df0SBarry Smith   }
110e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
1116d7c1e57SBarry Smith   PetscFunctionReturn(0);
1126d7c1e57SBarry Smith }
1136d7c1e57SBarry Smith 
114793850ffSBarry Smith PetscErrorCode MatMult_Composite(Mat A,Vec x,Vec y)
115793850ffSBarry Smith {
116793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
117793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
118793850ffSBarry Smith   PetscErrorCode    ierr;
119e4fc5df0SBarry Smith   Vec               in;
120793850ffSBarry Smith 
121793850ffSBarry Smith   PetscFunctionBegin;
122e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
123e4fc5df0SBarry Smith   in = x;
124e4fc5df0SBarry Smith   if (shell->right) {
125e4fc5df0SBarry Smith     if (!shell->rightwork) {
126e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr);
127793850ffSBarry Smith     }
128e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr);
129e4fc5df0SBarry Smith     in   = shell->rightwork;
130e4fc5df0SBarry Smith   }
131e4fc5df0SBarry Smith   ierr = MatMult(next->mat,in,y);CHKERRQ(ierr);
132e4fc5df0SBarry Smith   while ((next = next->next)) {
133e4fc5df0SBarry Smith     ierr = MatMultAdd(next->mat,in,y,y);CHKERRQ(ierr);
134e4fc5df0SBarry Smith   }
135e4fc5df0SBarry Smith   if (shell->left) {
136e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);
137e4fc5df0SBarry Smith   }
138e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
139793850ffSBarry Smith   PetscFunctionReturn(0);
140793850ffSBarry Smith }
141793850ffSBarry Smith 
142793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y)
143793850ffSBarry Smith {
144793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
145793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
146793850ffSBarry Smith   PetscErrorCode    ierr;
147e4fc5df0SBarry Smith   Vec               in;
148793850ffSBarry Smith 
149793850ffSBarry Smith   PetscFunctionBegin;
150e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
151e4fc5df0SBarry Smith   in = x;
152e4fc5df0SBarry Smith   if (shell->left) {
153e4fc5df0SBarry Smith     if (!shell->leftwork) {
154e4fc5df0SBarry Smith       ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr);
155793850ffSBarry Smith     }
156e4fc5df0SBarry Smith     ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr);
157e4fc5df0SBarry Smith     in   = shell->leftwork;
158e4fc5df0SBarry Smith   }
159e4fc5df0SBarry Smith   ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr);
160e4fc5df0SBarry Smith   while ((next = next->next)) {
161e4fc5df0SBarry Smith     ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr);
162e4fc5df0SBarry Smith   }
163e4fc5df0SBarry Smith   if (shell->right) {
164e4fc5df0SBarry Smith     ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr);
165e4fc5df0SBarry Smith   }
166e4fc5df0SBarry Smith   ierr = VecScale(y,shell->scale);CHKERRQ(ierr);
167793850ffSBarry Smith   PetscFunctionReturn(0);
168793850ffSBarry Smith }
169793850ffSBarry Smith 
170793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v)
171793850ffSBarry Smith {
172793850ffSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)A->data;
173793850ffSBarry Smith   Mat_CompositeLink next   = shell->head;
174793850ffSBarry Smith   PetscErrorCode    ierr;
175793850ffSBarry Smith 
176793850ffSBarry Smith   PetscFunctionBegin;
177e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
178e32f2f54SBarry Smith   if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling");
179e4fc5df0SBarry Smith 
180793850ffSBarry Smith   ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr);
181793850ffSBarry Smith   if (next->next && !shell->work) {
182793850ffSBarry Smith     ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr);
183793850ffSBarry Smith   }
184793850ffSBarry Smith   while ((next = next->next)) {
185793850ffSBarry Smith     ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr);
186793850ffSBarry Smith     ierr = VecAXPY(v,1.0,shell->work);CHKERRQ(ierr);
187793850ffSBarry Smith   }
188e4fc5df0SBarry Smith   ierr = VecScale(v,shell->scale);CHKERRQ(ierr);
189793850ffSBarry Smith   PetscFunctionReturn(0);
190793850ffSBarry Smith }
191793850ffSBarry Smith 
192793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t)
193793850ffSBarry Smith {
194b52f573bSBarry Smith   PetscErrorCode ierr;
195ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
196b52f573bSBarry Smith 
197793850ffSBarry Smith   PetscFunctionBegin;
198c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)Y)->options,((PetscObject)Y)->prefix,"-mat_composite_merge",&flg,NULL);CHKERRQ(ierr);
199b52f573bSBarry Smith   if (flg) {
200b52f573bSBarry Smith     ierr = MatCompositeMerge(Y);CHKERRQ(ierr);
201b52f573bSBarry Smith   }
202793850ffSBarry Smith   PetscFunctionReturn(0);
203793850ffSBarry Smith }
204793850ffSBarry Smith 
205e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha)
206e4fc5df0SBarry Smith {
207e4fc5df0SBarry Smith   Mat_Composite *a = (Mat_Composite*)inA->data;
208e4fc5df0SBarry Smith 
209e4fc5df0SBarry Smith   PetscFunctionBegin;
210321429dbSBarry Smith   a->scale *= alpha;
211e4fc5df0SBarry Smith   PetscFunctionReturn(0);
212e4fc5df0SBarry Smith }
213e4fc5df0SBarry Smith 
214e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right)
215e4fc5df0SBarry Smith {
216e4fc5df0SBarry Smith   Mat_Composite  *a = (Mat_Composite*)inA->data;
217e4fc5df0SBarry Smith   PetscErrorCode ierr;
218e4fc5df0SBarry Smith 
219e4fc5df0SBarry Smith   PetscFunctionBegin;
220e4fc5df0SBarry Smith   if (left) {
221321429dbSBarry Smith     if (!a->left) {
222e4fc5df0SBarry Smith       ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr);
223e4fc5df0SBarry Smith       ierr = VecCopy(left,a->left);CHKERRQ(ierr);
224321429dbSBarry Smith     } else {
225321429dbSBarry Smith       ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr);
226321429dbSBarry Smith     }
227e4fc5df0SBarry Smith   }
228e4fc5df0SBarry Smith   if (right) {
229321429dbSBarry Smith     if (!a->right) {
230e4fc5df0SBarry Smith       ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr);
231e4fc5df0SBarry Smith       ierr = VecCopy(right,a->right);CHKERRQ(ierr);
232321429dbSBarry Smith     } else {
233321429dbSBarry Smith       ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr);
234321429dbSBarry Smith     }
235e4fc5df0SBarry Smith   }
236e4fc5df0SBarry Smith   PetscFunctionReturn(0);
237e4fc5df0SBarry Smith }
238793850ffSBarry Smith 
239793850ffSBarry Smith static struct _MatOps MatOps_Values = {0,
240793850ffSBarry Smith                                        0,
241793850ffSBarry Smith                                        0,
242793850ffSBarry Smith                                        MatMult_Composite,
243793850ffSBarry Smith                                        0,
244793850ffSBarry Smith                                 /*  5*/ MatMultTranspose_Composite,
245793850ffSBarry Smith                                        0,
246793850ffSBarry Smith                                        0,
247793850ffSBarry Smith                                        0,
248793850ffSBarry Smith                                        0,
249793850ffSBarry Smith                                 /* 10*/ 0,
250793850ffSBarry Smith                                        0,
251793850ffSBarry Smith                                        0,
252793850ffSBarry Smith                                        0,
253793850ffSBarry Smith                                        0,
254793850ffSBarry Smith                                 /* 15*/ 0,
255793850ffSBarry Smith                                        0,
256793850ffSBarry Smith                                        MatGetDiagonal_Composite,
257e4fc5df0SBarry Smith                                        MatDiagonalScale_Composite,
258793850ffSBarry Smith                                        0,
259793850ffSBarry Smith                                 /* 20*/ 0,
260793850ffSBarry Smith                                        MatAssemblyEnd_Composite,
261793850ffSBarry Smith                                        0,
262793850ffSBarry Smith                                        0,
263d519adbfSMatthew Knepley                                /* 24*/ 0,
264793850ffSBarry Smith                                        0,
265793850ffSBarry Smith                                        0,
266793850ffSBarry Smith                                        0,
267793850ffSBarry Smith                                        0,
268d519adbfSMatthew Knepley                                /* 29*/ 0,
269793850ffSBarry Smith                                        0,
270793850ffSBarry Smith                                        0,
271793850ffSBarry Smith                                        0,
272793850ffSBarry Smith                                        0,
273d519adbfSMatthew Knepley                                /* 34*/ 0,
274793850ffSBarry Smith                                        0,
275793850ffSBarry Smith                                        0,
276793850ffSBarry Smith                                        0,
277793850ffSBarry Smith                                        0,
278d519adbfSMatthew Knepley                                /* 39*/ 0,
279793850ffSBarry Smith                                        0,
280793850ffSBarry Smith                                        0,
281793850ffSBarry Smith                                        0,
282793850ffSBarry Smith                                        0,
283d519adbfSMatthew Knepley                                /* 44*/ 0,
284e4fc5df0SBarry Smith                                        MatScale_Composite,
2857d68702bSBarry Smith                                        MatShift_Basic,
286793850ffSBarry Smith                                        0,
287793850ffSBarry Smith                                        0,
288d519adbfSMatthew Knepley                                /* 49*/ 0,
289793850ffSBarry Smith                                        0,
290793850ffSBarry Smith                                        0,
291793850ffSBarry Smith                                        0,
292793850ffSBarry Smith                                        0,
293d519adbfSMatthew Knepley                                /* 54*/ 0,
294793850ffSBarry Smith                                        0,
295793850ffSBarry Smith                                        0,
296793850ffSBarry Smith                                        0,
297793850ffSBarry Smith                                        0,
298d519adbfSMatthew Knepley                                /* 59*/ 0,
299793850ffSBarry Smith                                        MatDestroy_Composite,
300793850ffSBarry Smith                                        0,
301793850ffSBarry Smith                                        0,
302793850ffSBarry Smith                                        0,
303d519adbfSMatthew Knepley                                /* 64*/ 0,
304793850ffSBarry Smith                                        0,
305793850ffSBarry Smith                                        0,
306793850ffSBarry Smith                                        0,
307793850ffSBarry Smith                                        0,
308d519adbfSMatthew Knepley                                /* 69*/ 0,
309793850ffSBarry Smith                                        0,
310793850ffSBarry Smith                                        0,
311793850ffSBarry Smith                                        0,
312793850ffSBarry Smith                                        0,
313d519adbfSMatthew Knepley                                /* 74*/ 0,
314793850ffSBarry Smith                                        0,
315793850ffSBarry Smith                                        0,
316793850ffSBarry Smith                                        0,
317793850ffSBarry Smith                                        0,
318d519adbfSMatthew Knepley                                /* 79*/ 0,
319793850ffSBarry Smith                                        0,
320793850ffSBarry Smith                                        0,
321793850ffSBarry Smith                                        0,
322793850ffSBarry Smith                                        0,
323d519adbfSMatthew Knepley                                /* 84*/ 0,
324793850ffSBarry Smith                                        0,
325793850ffSBarry Smith                                        0,
326793850ffSBarry Smith                                        0,
327793850ffSBarry Smith                                        0,
328d519adbfSMatthew Knepley                                /* 89*/ 0,
329793850ffSBarry Smith                                        0,
330793850ffSBarry Smith                                        0,
331793850ffSBarry Smith                                        0,
332793850ffSBarry Smith                                        0,
333d519adbfSMatthew Knepley                                /* 94*/ 0,
334793850ffSBarry Smith                                        0,
335793850ffSBarry Smith                                        0,
3363964eb88SJed Brown                                        0,
3373964eb88SJed Brown                                        0,
3383964eb88SJed Brown                                 /*99*/ 0,
3393964eb88SJed Brown                                        0,
3403964eb88SJed Brown                                        0,
3413964eb88SJed Brown                                        0,
3423964eb88SJed Brown                                        0,
3433964eb88SJed Brown                                /*104*/ 0,
3443964eb88SJed Brown                                        0,
3453964eb88SJed Brown                                        0,
3463964eb88SJed Brown                                        0,
3473964eb88SJed Brown                                        0,
3483964eb88SJed Brown                                /*109*/ 0,
3493964eb88SJed Brown                                        0,
3503964eb88SJed Brown                                        0,
3513964eb88SJed Brown                                        0,
3523964eb88SJed Brown                                        0,
3533964eb88SJed Brown                                /*114*/ 0,
3543964eb88SJed Brown                                        0,
3553964eb88SJed Brown                                        0,
3563964eb88SJed Brown                                        0,
3573964eb88SJed Brown                                        0,
3583964eb88SJed Brown                                /*119*/ 0,
3593964eb88SJed Brown                                        0,
3603964eb88SJed Brown                                        0,
3613964eb88SJed Brown                                        0,
3623964eb88SJed Brown                                        0,
3633964eb88SJed Brown                                /*124*/ 0,
3643964eb88SJed Brown                                        0,
3653964eb88SJed Brown                                        0,
3663964eb88SJed Brown                                        0,
3673964eb88SJed Brown                                        0,
3683964eb88SJed Brown                                /*129*/ 0,
3693964eb88SJed Brown                                        0,
3703964eb88SJed Brown                                        0,
3713964eb88SJed Brown                                        0,
3723964eb88SJed Brown                                        0,
3733964eb88SJed Brown                                /*134*/ 0,
3743964eb88SJed Brown                                        0,
3753964eb88SJed Brown                                        0,
3763964eb88SJed Brown                                        0,
3773964eb88SJed Brown                                        0,
3783964eb88SJed Brown                                /*139*/ 0,
379f9426fe0SMark Adams                                        0,
3803964eb88SJed Brown                                        0
3813964eb88SJed Brown };
382793850ffSBarry Smith 
383793850ffSBarry Smith /*MC
3846d7c1e57SBarry Smith    MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices (all matrices are of same size and parallel layout).
3856d7c1e57SBarry Smith 
38695452b02SPatrick Sanan    Notes:
38795452b02SPatrick Sanan     to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE);
388793850ffSBarry Smith 
389793850ffSBarry Smith   Level: advanced
390793850ffSBarry Smith 
3916d7c1e57SBarry Smith .seealso: MatCreateComposite(), MatCompositeAddMat(), MatSetType(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType
392793850ffSBarry Smith M*/
393793850ffSBarry Smith 
3948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A)
395793850ffSBarry Smith {
396793850ffSBarry Smith   Mat_Composite  *b;
397793850ffSBarry Smith   PetscErrorCode ierr;
398793850ffSBarry Smith 
399793850ffSBarry Smith   PetscFunctionBegin;
400b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
401793850ffSBarry Smith   A->data = (void*)b;
40238f2d2fdSLisandro Dalcin   ierr    = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
403793850ffSBarry Smith 
40426283091SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
40526283091SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
406793850ffSBarry Smith 
407793850ffSBarry Smith   A->assembled    = PETSC_TRUE;
4083db03f37SJed Brown   A->preallocated = PETSC_TRUE;
4096d7c1e57SBarry Smith   b->type         = MAT_COMPOSITE_ADDITIVE;
410e4fc5df0SBarry Smith   b->scale        = 1.0;
411*6a7ede75SJakub Kruzik   b->nmat         = 0;
412793850ffSBarry Smith   ierr            = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr);
413793850ffSBarry Smith   PetscFunctionReturn(0);
414793850ffSBarry Smith }
415793850ffSBarry Smith 
4162c0821f3SBarry Smith /*@
417793850ffSBarry Smith    MatCreateComposite - Creates a matrix as the sum of zero or more matrices
418793850ffSBarry Smith 
419793850ffSBarry Smith   Collective on MPI_Comm
420793850ffSBarry Smith 
421793850ffSBarry Smith    Input Parameters:
422793850ffSBarry Smith +  comm - MPI communicator
423793850ffSBarry Smith .  nmat - number of matrices to put in
424793850ffSBarry Smith -  mats - the matrices
425793850ffSBarry Smith 
426793850ffSBarry Smith    Output Parameter:
427db36af27SMatthew G. Knepley .  mat - the matrix
428793850ffSBarry Smith 
429793850ffSBarry Smith    Level: advanced
430793850ffSBarry Smith 
431793850ffSBarry Smith    Notes:
432793850ffSBarry Smith      Alternative construction
433793850ffSBarry Smith $       MatCreate(comm,&mat);
434793850ffSBarry Smith $       MatSetSizes(mat,m,n,M,N);
435793850ffSBarry Smith $       MatSetType(mat,MATCOMPOSITE);
436793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[0]);
437793850ffSBarry Smith $       ....
438793850ffSBarry Smith $       MatCompositeAddMat(mat,mats[nmat-1]);
439b52f573bSBarry Smith $       MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
440b52f573bSBarry Smith $       MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
441793850ffSBarry Smith 
4426d7c1e57SBarry Smith      For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0]
4436d7c1e57SBarry Smith 
4446d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeMerge(), MatCompositeSetType(), MatCompositeType
445793850ffSBarry Smith 
446793850ffSBarry Smith @*/
4477087cfbeSBarry Smith PetscErrorCode  MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat)
448793850ffSBarry Smith {
449793850ffSBarry Smith   PetscErrorCode ierr;
450793850ffSBarry Smith   PetscInt       m,n,M,N,i;
451793850ffSBarry Smith 
452793850ffSBarry Smith   PetscFunctionBegin;
453e32f2f54SBarry Smith   if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix");
454f3f84630SBarry Smith   PetscValidPointer(mat,3);
455793850ffSBarry Smith 
456793850ffSBarry Smith   ierr = MatGetLocalSize(mats[0],&m,&n);CHKERRQ(ierr);
457793850ffSBarry Smith   ierr = MatGetSize(mats[0],&M,&N);CHKERRQ(ierr);
458793850ffSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
459793850ffSBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
460793850ffSBarry Smith   ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr);
461793850ffSBarry Smith   for (i=0; i<nmat; i++) {
462793850ffSBarry Smith     ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr);
463793850ffSBarry Smith   }
464b52f573bSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
465b52f573bSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
466793850ffSBarry Smith   PetscFunctionReturn(0);
467793850ffSBarry Smith }
468793850ffSBarry Smith 
469793850ffSBarry Smith /*@
470793850ffSBarry Smith     MatCompositeAddMat - add another matrix to a composite matrix
471793850ffSBarry Smith 
472793850ffSBarry Smith    Collective on Mat
473793850ffSBarry Smith 
474793850ffSBarry Smith     Input Parameters:
475793850ffSBarry Smith +   mat - the composite matrix
476793850ffSBarry Smith -   smat - the partial matrix
477793850ffSBarry Smith 
478793850ffSBarry Smith    Level: advanced
479793850ffSBarry Smith 
480793850ffSBarry Smith .seealso: MatCreateComposite()
481793850ffSBarry Smith @*/
4827087cfbeSBarry Smith PetscErrorCode  MatCompositeAddMat(Mat mat,Mat smat)
483793850ffSBarry Smith {
48438f2d2fdSLisandro Dalcin   Mat_Composite     *shell;
485793850ffSBarry Smith   PetscErrorCode    ierr;
486793850ffSBarry Smith   Mat_CompositeLink ilink,next;
487793850ffSBarry Smith 
488793850ffSBarry Smith   PetscFunctionBegin;
4890700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
4900700a824SBarry Smith   PetscValidHeaderSpecific(smat,MAT_CLASSID,2);
491b00a9115SJed Brown   ierr        = PetscNewLog(mat,&ilink);CHKERRQ(ierr);
492793850ffSBarry Smith   ilink->next = 0;
493793850ffSBarry Smith   ierr        = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr);
494c3122656SLisandro Dalcin   ilink->mat  = smat;
495793850ffSBarry Smith 
49638f2d2fdSLisandro Dalcin   shell = (Mat_Composite*)mat->data;
497793850ffSBarry Smith   next  = shell->head;
4982205254eSKarl Rupp   if (!next) shell->head = ilink;
4992205254eSKarl Rupp   else {
500793850ffSBarry Smith     while (next->next) {
501793850ffSBarry Smith       next = next->next;
502793850ffSBarry Smith     }
503793850ffSBarry Smith     next->next  = ilink;
5046d7c1e57SBarry Smith     ilink->prev = next;
5056d7c1e57SBarry Smith   }
5066d7c1e57SBarry Smith   shell->tail =  ilink;
507*6a7ede75SJakub Kruzik   shell->nmat += 1;
5086d7c1e57SBarry Smith   PetscFunctionReturn(0);
5096d7c1e57SBarry Smith }
5106d7c1e57SBarry Smith 
5112c0821f3SBarry Smith /*@
5126d7c1e57SBarry Smith    MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product
5136d7c1e57SBarry Smith 
5146d7c1e57SBarry Smith   Collective on MPI_Comm
5156d7c1e57SBarry Smith 
5166d7c1e57SBarry Smith    Input Parameters:
5176d7c1e57SBarry Smith .  mat - the composite matrix
5186d7c1e57SBarry Smith 
5196d7c1e57SBarry Smith 
5206d7c1e57SBarry Smith    Level: advanced
5216d7c1e57SBarry Smith 
5226d7c1e57SBarry Smith    Notes:
5236d7c1e57SBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
5246d7c1e57SBarry Smith     matrix in the composite matrix.
5256d7c1e57SBarry Smith 
5266d7c1e57SBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
5276d7c1e57SBarry Smith 
5286d7c1e57SBarry Smith @*/
5297087cfbeSBarry Smith PetscErrorCode  MatCompositeSetType(Mat mat,MatCompositeType type)
5306d7c1e57SBarry Smith {
5316d7c1e57SBarry Smith   Mat_Composite  *b = (Mat_Composite*)mat->data;
532ace3abfcSBarry Smith   PetscBool      flg;
5336d7c1e57SBarry Smith   PetscErrorCode ierr;
5346d7c1e57SBarry Smith 
5356d7c1e57SBarry Smith   PetscFunctionBegin;
536251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)mat,MATCOMPOSITE,&flg);CHKERRQ(ierr);
537e32f2f54SBarry Smith   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Can only use with composite matrix");
5386d7c1e57SBarry Smith   if (type == MAT_COMPOSITE_MULTIPLICATIVE) {
5396d7c1e57SBarry Smith     mat->ops->getdiagonal   = 0;
5406d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite_Multiplicative;
5416d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative;
5426d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_MULTIPLICATIVE;
5436d7c1e57SBarry Smith   } else {
5446d7c1e57SBarry Smith     mat->ops->getdiagonal   = MatGetDiagonal_Composite;
5456d7c1e57SBarry Smith     mat->ops->mult          = MatMult_Composite;
5466d7c1e57SBarry Smith     mat->ops->multtranspose = MatMultTranspose_Composite;
5476d7c1e57SBarry Smith     b->type                 = MAT_COMPOSITE_ADDITIVE;
548793850ffSBarry Smith   }
549793850ffSBarry Smith   PetscFunctionReturn(0);
550793850ffSBarry Smith }
551793850ffSBarry Smith 
5526d7c1e57SBarry Smith 
5537e8dbf47SJed Brown /*@
554b52f573bSBarry Smith    MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix
555b52f573bSBarry Smith      by summing all the matrices inside the composite matrix.
556b52f573bSBarry Smith 
557b52f573bSBarry Smith   Collective on MPI_Comm
558b52f573bSBarry Smith 
559b52f573bSBarry Smith    Input Parameters:
560b52f573bSBarry Smith .  mat - the composite matrix
561b52f573bSBarry Smith 
562b52f573bSBarry Smith 
563b52f573bSBarry Smith    Options Database:
564b52f573bSBarry Smith .  -mat_composite_merge  (you must call MatAssemblyBegin()/MatAssemblyEnd() to have this checked)
565b52f573bSBarry Smith 
566b52f573bSBarry Smith    Level: advanced
567b52f573bSBarry Smith 
568b52f573bSBarry Smith    Notes:
569b52f573bSBarry Smith       The MatType of the resulting matrix will be the same as the MatType of the FIRST
570b52f573bSBarry Smith     matrix in the composite matrix.
571b52f573bSBarry Smith 
572b52f573bSBarry Smith .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MATCOMPOSITE
573b52f573bSBarry Smith 
574b52f573bSBarry Smith @*/
5757087cfbeSBarry Smith PetscErrorCode  MatCompositeMerge(Mat mat)
576b52f573bSBarry Smith {
577b52f573bSBarry Smith   Mat_Composite     *shell = (Mat_Composite*)mat->data;
5786d7c1e57SBarry Smith   Mat_CompositeLink next   = shell->head, prev = shell->tail;
579b52f573bSBarry Smith   PetscErrorCode    ierr;
5806d7c1e57SBarry Smith   Mat               tmat,newmat;
5811ba60692SJed Brown   Vec               left,right;
5821ba60692SJed Brown   PetscScalar       scale;
583b52f573bSBarry Smith 
584b52f573bSBarry Smith   PetscFunctionBegin;
585e32f2f54SBarry Smith   if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()");
586b52f573bSBarry Smith 
587b52f573bSBarry Smith   PetscFunctionBegin;
5886d7c1e57SBarry Smith   if (shell->type == MAT_COMPOSITE_ADDITIVE) {
589b52f573bSBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
590b52f573bSBarry Smith     while ((next = next->next)) {
591b52f573bSBarry Smith       ierr = MatAXPY(tmat,1.0,next->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
592b52f573bSBarry Smith     }
5936d7c1e57SBarry Smith   } else {
5946d7c1e57SBarry Smith     ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5956d7c1e57SBarry Smith     while ((prev = prev->prev)) {
5966d7c1e57SBarry Smith       ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr);
5976bf464f9SBarry Smith       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5986d7c1e57SBarry Smith       tmat = newmat;
5996d7c1e57SBarry Smith     }
6006d7c1e57SBarry Smith   }
6011ba60692SJed Brown 
6021ba60692SJed Brown   scale = shell->scale;
6031ba60692SJed Brown   if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);}
6041ba60692SJed Brown   if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);}
6051ba60692SJed Brown 
60628be2f97SBarry Smith   ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr);
6071ba60692SJed Brown 
6081ba60692SJed Brown   ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr);
6091ba60692SJed Brown   ierr = MatScale(mat,scale);CHKERRQ(ierr);
6101ba60692SJed Brown   ierr = VecDestroy(&left);CHKERRQ(ierr);
6111ba60692SJed Brown   ierr = VecDestroy(&right);CHKERRQ(ierr);
612b52f573bSBarry Smith   PetscFunctionReturn(0);
613b52f573bSBarry Smith }
614*6a7ede75SJakub Kruzik 
615*6a7ede75SJakub Kruzik /*@
616*6a7ede75SJakub Kruzik    MatCompositeGetNMat - Returns the number of matrices in composite.
617*6a7ede75SJakub Kruzik 
618*6a7ede75SJakub Kruzik    Not Collective
619*6a7ede75SJakub Kruzik 
620*6a7ede75SJakub Kruzik    Input Parameter:
621*6a7ede75SJakub Kruzik .  A - the composite matrix
622*6a7ede75SJakub Kruzik 
623*6a7ede75SJakub Kruzik    Output Parameter:
624*6a7ede75SJakub Kruzik .  size - the local size
625*6a7ede75SJakub Kruzik .  nmat - number of matrices in composite
626*6a7ede75SJakub Kruzik 
627*6a7ede75SJakub Kruzik    Level: beginner
628*6a7ede75SJakub Kruzik 
629*6a7ede75SJakub Kruzik .seealso: MatCreateComposite()
630*6a7ede75SJakub Kruzik 
631*6a7ede75SJakub Kruzik @*/
632*6a7ede75SJakub Kruzik PetscErrorCode MatCompositeGetNMat(Mat A,PetscInt *nmat)
633*6a7ede75SJakub Kruzik {
634*6a7ede75SJakub Kruzik   Mat_Composite  *shell;
635*6a7ede75SJakub Kruzik 
636*6a7ede75SJakub Kruzik   PetscFunctionBegin;
637*6a7ede75SJakub Kruzik   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
638*6a7ede75SJakub Kruzik   PetscValidPointer(nmat,2);
639*6a7ede75SJakub Kruzik   shell = (Mat_Composite*)A->data;
640*6a7ede75SJakub Kruzik   *nmat = shell->nmat;
641*6a7ede75SJakub Kruzik   PetscFunctionReturn(0);
642*6a7ede75SJakub Kruzik }
643*6a7ede75SJakub Kruzik 
644