Actual source code: maij.c

petsc-3.7.3 2016-08-01
Report Typos and Errors
  2: /*
  3:     Defines the basic matrix operations for the MAIJ  matrix storage format.
  4:   This format is used for restriction and interpolation operations for
  5:   multicomponent problems. It interpolates each component the same way
  6:   independently.

  8:      We provide:
  9:          MatMult()
 10:          MatMultTranspose()
 11:          MatMultTransposeAdd()
 12:          MatMultAdd()
 13:           and
 14:          MatCreateMAIJ(Mat,dof,Mat*)

 16:      This single directory handles both the sequential and parallel codes
 17: */

 19: #include <../src/mat/impls/maij/maij.h> /*I "petscmat.h" I*/
 20: #include <../src/mat/utils/freespace.h>
 21: #include <petsc/private/vecimpl.h>

 25: /*@
 26:    MatMAIJGetAIJ - Get the AIJ matrix describing the blockwise action of the MAIJ matrix

 28:    Not Collective, but if the MAIJ matrix is parallel, the AIJ matrix is also parallel

 30:    Input Parameter:
 31: .  A - the MAIJ matrix

 33:    Output Parameter:
 34: .  B - the AIJ matrix

 36:    Level: advanced

 38:    Notes: The reference count on the AIJ matrix is not increased so you should not destroy it.

 40: .seealso: MatCreateMAIJ()
 41: @*/
 42: PetscErrorCode  MatMAIJGetAIJ(Mat A,Mat *B)
 43: {
 45:   PetscBool      ismpimaij,isseqmaij;

 48:   PetscObjectTypeCompare((PetscObject)A,MATMPIMAIJ,&ismpimaij);
 49:   PetscObjectTypeCompare((PetscObject)A,MATSEQMAIJ,&isseqmaij);
 50:   if (ismpimaij) {
 51:     Mat_MPIMAIJ *b = (Mat_MPIMAIJ*)A->data;

 53:     *B = b->A;
 54:   } else if (isseqmaij) {
 55:     Mat_SeqMAIJ *b = (Mat_SeqMAIJ*)A->data;

 57:     *B = b->AIJ;
 58:   } else {
 59:     *B = A;
 60:   }
 61:   return(0);
 62: }

 66: /*@C
 67:    MatMAIJRedimension - Get an MAIJ matrix with the same action, but for a different block size

 69:    Logically Collective

 71:    Input Parameter:
 72: +  A - the MAIJ matrix
 73: -  dof - the block size for the new matrix

 75:    Output Parameter:
 76: .  B - the new MAIJ matrix

 78:    Level: advanced

 80: .seealso: MatCreateMAIJ()
 81: @*/
 82: PetscErrorCode  MatMAIJRedimension(Mat A,PetscInt dof,Mat *B)
 83: {
 85:   Mat            Aij = NULL;

 89:   MatMAIJGetAIJ(A,&Aij);
 90:   MatCreateMAIJ(Aij,dof,B);
 91:   return(0);
 92: }

 96: PetscErrorCode MatDestroy_SeqMAIJ(Mat A)
 97: {
 99:   Mat_SeqMAIJ    *b = (Mat_SeqMAIJ*)A->data;

102:   MatDestroy(&b->AIJ);
103:   PetscFree(A->data);
104:   PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqmaij_seqaij_C",NULL);
105:   PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_seqmaij_C",NULL);
106:   return(0);
107: }

111: PetscErrorCode MatSetUp_MAIJ(Mat A)
112: {
114:   SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Must use MatCreateMAIJ() to create MAIJ matrices");
115:   return(0);
116: }

120: PetscErrorCode MatView_SeqMAIJ(Mat A,PetscViewer viewer)
121: {
123:   Mat            B;

126:   MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);
127:   MatView(B,viewer);
128:   MatDestroy(&B);
129:   return(0);
130: }

134: PetscErrorCode MatView_MPIMAIJ(Mat A,PetscViewer viewer)
135: {
137:   Mat            B;

140:   MatConvert(A,MATMPIAIJ,MAT_INITIAL_MATRIX,&B);
141:   MatView(B,viewer);
142:   MatDestroy(&B);
143:   return(0);
144: }

148: PetscErrorCode MatDestroy_MPIMAIJ(Mat A)
149: {
151:   Mat_MPIMAIJ    *b = (Mat_MPIMAIJ*)A->data;

154:   MatDestroy(&b->AIJ);
155:   MatDestroy(&b->OAIJ);
156:   MatDestroy(&b->A);
157:   VecScatterDestroy(&b->ctx);
158:   VecDestroy(&b->w);
159:   PetscFree(A->data);
160:   PetscObjectComposeFunction((PetscObject)A,"MatConvert_mpimaij_mpiaij_C",NULL);
161:   PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_mpimaij_C",NULL);
162:   PetscObjectChangeTypeName((PetscObject)A,0);
163:   return(0);
164: }

166: /*MC
167:   MATMAIJ - MATMAIJ = "maij" - A matrix type to be used for restriction and interpolation operations for
168:   multicomponent problems, interpolating or restricting each component the same way independently.
169:   The matrix type is based on MATSEQAIJ for sequential matrices, and MATMPIAIJ for distributed matrices.

171:   Operations provided:
172: . MatMult
173: . MatMultTranspose
174: . MatMultAdd
175: . MatMultTransposeAdd

177:   Level: advanced

179: .seealso: MatMAIJGetAIJ(), MatMAIJRedimension(), MatCreateMAIJ()
180: M*/

184: PETSC_EXTERN PetscErrorCode MatCreate_MAIJ(Mat A)
185: {
187:   Mat_MPIMAIJ    *b;
188:   PetscMPIInt    size;

191:   PetscNewLog(A,&b);
192:   A->data  = (void*)b;

194:   PetscMemzero(A->ops,sizeof(struct _MatOps));

196:   A->ops->setup = MatSetUp_MAIJ;

198:   b->AIJ  = 0;
199:   b->dof  = 0;
200:   b->OAIJ = 0;
201:   b->ctx  = 0;
202:   b->w    = 0;
203:   MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);
204:   if (size == 1) {
205:     PetscObjectChangeTypeName((PetscObject)A,MATSEQMAIJ);
206:   } else {
207:     PetscObjectChangeTypeName((PetscObject)A,MATMPIMAIJ);
208:   }
209:   A->preallocated  = PETSC_TRUE;
210:   A->assembled     = PETSC_TRUE;
211:   return(0);
212: }

214: /* --------------------------------------------------------------------------------------*/
217: PetscErrorCode MatMult_SeqMAIJ_2(Mat A,Vec xx,Vec yy)
218: {
219:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
220:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
221:   const PetscScalar *x,*v;
222:   PetscScalar       *y, sum1, sum2;
223:   PetscErrorCode    ierr;
224:   PetscInt          nonzerorow=0,n,i,jrow,j;
225:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;

228:   VecGetArrayRead(xx,&x);
229:   VecGetArray(yy,&y);
230:   idx  = a->j;
231:   v    = a->a;
232:   ii   = a->i;

234:   for (i=0; i<m; i++) {
235:     jrow  = ii[i];
236:     n     = ii[i+1] - jrow;
237:     sum1  = 0.0;
238:     sum2  = 0.0;

240:     nonzerorow += (n>0);
241:     for (j=0; j<n; j++) {
242:       sum1 += v[jrow]*x[2*idx[jrow]];
243:       sum2 += v[jrow]*x[2*idx[jrow]+1];
244:       jrow++;
245:     }
246:     y[2*i]   = sum1;
247:     y[2*i+1] = sum2;
248:   }

250:   PetscLogFlops(4.0*a->nz - 2.0*nonzerorow);
251:   VecRestoreArrayRead(xx,&x);
252:   VecRestoreArray(yy,&y);
253:   return(0);
254: }

258: PetscErrorCode MatMultTranspose_SeqMAIJ_2(Mat A,Vec xx,Vec yy)
259: {
260:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
261:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
262:   const PetscScalar *x,*v;
263:   PetscScalar       *y,alpha1,alpha2;
264:   PetscErrorCode    ierr;
265:   PetscInt          n,i;
266:   const PetscInt    m = b->AIJ->rmap->n,*idx;

269:   VecSet(yy,0.0);
270:   VecGetArrayRead(xx,&x);
271:   VecGetArray(yy,&y);

273:   for (i=0; i<m; i++) {
274:     idx    = a->j + a->i[i];
275:     v      = a->a + a->i[i];
276:     n      = a->i[i+1] - a->i[i];
277:     alpha1 = x[2*i];
278:     alpha2 = x[2*i+1];
279:     while (n-->0) {
280:       y[2*(*idx)]   += alpha1*(*v);
281:       y[2*(*idx)+1] += alpha2*(*v);
282:       idx++; v++;
283:     }
284:   }
285:   PetscLogFlops(4.0*a->nz);
286:   VecRestoreArrayRead(xx,&x);
287:   VecRestoreArray(yy,&y);
288:   return(0);
289: }

293: PetscErrorCode MatMultAdd_SeqMAIJ_2(Mat A,Vec xx,Vec yy,Vec zz)
294: {
295:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
296:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
297:   const PetscScalar *x,*v;
298:   PetscScalar       *y,sum1, sum2;
299:   PetscErrorCode    ierr;
300:   PetscInt          n,i,jrow,j;
301:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;

304:   if (yy != zz) {VecCopy(yy,zz);}
305:   VecGetArrayRead(xx,&x);
306:   VecGetArray(zz,&y);
307:   idx  = a->j;
308:   v    = a->a;
309:   ii   = a->i;

311:   for (i=0; i<m; i++) {
312:     jrow = ii[i];
313:     n    = ii[i+1] - jrow;
314:     sum1 = 0.0;
315:     sum2 = 0.0;
316:     for (j=0; j<n; j++) {
317:       sum1 += v[jrow]*x[2*idx[jrow]];
318:       sum2 += v[jrow]*x[2*idx[jrow]+1];
319:       jrow++;
320:     }
321:     y[2*i]   += sum1;
322:     y[2*i+1] += sum2;
323:   }

325:   PetscLogFlops(4.0*a->nz);
326:   VecRestoreArrayRead(xx,&x);
327:   VecRestoreArray(zz,&y);
328:   return(0);
329: }
332: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_2(Mat A,Vec xx,Vec yy,Vec zz)
333: {
334:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
335:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
336:   const PetscScalar *x,*v;
337:   PetscScalar       *y,alpha1,alpha2;
338:   PetscErrorCode    ierr;
339:   PetscInt          n,i;
340:   const PetscInt    m = b->AIJ->rmap->n,*idx;

343:   if (yy != zz) {VecCopy(yy,zz);}
344:   VecGetArrayRead(xx,&x);
345:   VecGetArray(zz,&y);

347:   for (i=0; i<m; i++) {
348:     idx    = a->j + a->i[i];
349:     v      = a->a + a->i[i];
350:     n      = a->i[i+1] - a->i[i];
351:     alpha1 = x[2*i];
352:     alpha2 = x[2*i+1];
353:     while (n-->0) {
354:       y[2*(*idx)]   += alpha1*(*v);
355:       y[2*(*idx)+1] += alpha2*(*v);
356:       idx++; v++;
357:     }
358:   }
359:   PetscLogFlops(4.0*a->nz);
360:   VecRestoreArrayRead(xx,&x);
361:   VecRestoreArray(zz,&y);
362:   return(0);
363: }
364: /* --------------------------------------------------------------------------------------*/
367: PetscErrorCode MatMult_SeqMAIJ_3(Mat A,Vec xx,Vec yy)
368: {
369:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
370:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
371:   const PetscScalar *x,*v;
372:   PetscScalar       *y,sum1, sum2, sum3;
373:   PetscErrorCode    ierr;
374:   PetscInt          nonzerorow=0,n,i,jrow,j;
375:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;

378:   VecGetArrayRead(xx,&x);
379:   VecGetArray(yy,&y);
380:   idx  = a->j;
381:   v    = a->a;
382:   ii   = a->i;

384:   for (i=0; i<m; i++) {
385:     jrow  = ii[i];
386:     n     = ii[i+1] - jrow;
387:     sum1  = 0.0;
388:     sum2  = 0.0;
389:     sum3  = 0.0;

391:     nonzerorow += (n>0);
392:     for (j=0; j<n; j++) {
393:       sum1 += v[jrow]*x[3*idx[jrow]];
394:       sum2 += v[jrow]*x[3*idx[jrow]+1];
395:       sum3 += v[jrow]*x[3*idx[jrow]+2];
396:       jrow++;
397:      }
398:     y[3*i]   = sum1;
399:     y[3*i+1] = sum2;
400:     y[3*i+2] = sum3;
401:   }

403:   PetscLogFlops(6.0*a->nz - 3.0*nonzerorow);
404:   VecRestoreArrayRead(xx,&x);
405:   VecRestoreArray(yy,&y);
406:   return(0);
407: }

411: PetscErrorCode MatMultTranspose_SeqMAIJ_3(Mat A,Vec xx,Vec yy)
412: {
413:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
414:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
415:   const PetscScalar *x,*v;
416:   PetscScalar       *y,alpha1,alpha2,alpha3;
417:   PetscErrorCode    ierr;
418:   PetscInt          n,i;
419:   const PetscInt    m = b->AIJ->rmap->n,*idx;

422:   VecSet(yy,0.0);
423:   VecGetArrayRead(xx,&x);
424:   VecGetArray(yy,&y);

426:   for (i=0; i<m; i++) {
427:     idx    = a->j + a->i[i];
428:     v      = a->a + a->i[i];
429:     n      = a->i[i+1] - a->i[i];
430:     alpha1 = x[3*i];
431:     alpha2 = x[3*i+1];
432:     alpha3 = x[3*i+2];
433:     while (n-->0) {
434:       y[3*(*idx)]   += alpha1*(*v);
435:       y[3*(*idx)+1] += alpha2*(*v);
436:       y[3*(*idx)+2] += alpha3*(*v);
437:       idx++; v++;
438:     }
439:   }
440:   PetscLogFlops(6.0*a->nz);
441:   VecRestoreArrayRead(xx,&x);
442:   VecRestoreArray(yy,&y);
443:   return(0);
444: }

448: PetscErrorCode MatMultAdd_SeqMAIJ_3(Mat A,Vec xx,Vec yy,Vec zz)
449: {
450:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
451:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
452:   const PetscScalar *x,*v;
453:   PetscScalar       *y,sum1, sum2, sum3;
454:   PetscErrorCode    ierr;
455:   PetscInt          n,i,jrow,j;
456:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;

459:   if (yy != zz) {VecCopy(yy,zz);}
460:   VecGetArrayRead(xx,&x);
461:   VecGetArray(zz,&y);
462:   idx  = a->j;
463:   v    = a->a;
464:   ii   = a->i;

466:   for (i=0; i<m; i++) {
467:     jrow = ii[i];
468:     n    = ii[i+1] - jrow;
469:     sum1 = 0.0;
470:     sum2 = 0.0;
471:     sum3 = 0.0;
472:     for (j=0; j<n; j++) {
473:       sum1 += v[jrow]*x[3*idx[jrow]];
474:       sum2 += v[jrow]*x[3*idx[jrow]+1];
475:       sum3 += v[jrow]*x[3*idx[jrow]+2];
476:       jrow++;
477:     }
478:     y[3*i]   += sum1;
479:     y[3*i+1] += sum2;
480:     y[3*i+2] += sum3;
481:   }

483:   PetscLogFlops(6.0*a->nz);
484:   VecRestoreArrayRead(xx,&x);
485:   VecRestoreArray(zz,&y);
486:   return(0);
487: }
490: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_3(Mat A,Vec xx,Vec yy,Vec zz)
491: {
492:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
493:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
494:   const PetscScalar *x,*v;
495:   PetscScalar       *y,alpha1,alpha2,alpha3;
496:   PetscErrorCode    ierr;
497:   PetscInt          n,i;
498:   const PetscInt    m = b->AIJ->rmap->n,*idx;

501:   if (yy != zz) {VecCopy(yy,zz);}
502:   VecGetArrayRead(xx,&x);
503:   VecGetArray(zz,&y);
504:   for (i=0; i<m; i++) {
505:     idx    = a->j + a->i[i];
506:     v      = a->a + a->i[i];
507:     n      = a->i[i+1] - a->i[i];
508:     alpha1 = x[3*i];
509:     alpha2 = x[3*i+1];
510:     alpha3 = x[3*i+2];
511:     while (n-->0) {
512:       y[3*(*idx)]   += alpha1*(*v);
513:       y[3*(*idx)+1] += alpha2*(*v);
514:       y[3*(*idx)+2] += alpha3*(*v);
515:       idx++; v++;
516:     }
517:   }
518:   PetscLogFlops(6.0*a->nz);
519:   VecRestoreArrayRead(xx,&x);
520:   VecRestoreArray(zz,&y);
521:   return(0);
522: }

524: /* ------------------------------------------------------------------------------*/
527: PetscErrorCode MatMult_SeqMAIJ_4(Mat A,Vec xx,Vec yy)
528: {
529:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
530:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
531:   const PetscScalar *x,*v;
532:   PetscScalar       *y,sum1, sum2, sum3, sum4;
533:   PetscErrorCode    ierr;
534:   PetscInt          nonzerorow=0,n,i,jrow,j;
535:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;

538:   VecGetArrayRead(xx,&x);
539:   VecGetArray(yy,&y);
540:   idx  = a->j;
541:   v    = a->a;
542:   ii   = a->i;

544:   for (i=0; i<m; i++) {
545:     jrow        = ii[i];
546:     n           = ii[i+1] - jrow;
547:     sum1        = 0.0;
548:     sum2        = 0.0;
549:     sum3        = 0.0;
550:     sum4        = 0.0;
551:     nonzerorow += (n>0);
552:     for (j=0; j<n; j++) {
553:       sum1 += v[jrow]*x[4*idx[jrow]];
554:       sum2 += v[jrow]*x[4*idx[jrow]+1];
555:       sum3 += v[jrow]*x[4*idx[jrow]+2];
556:       sum4 += v[jrow]*x[4*idx[jrow]+3];
557:       jrow++;
558:     }
559:     y[4*i]   = sum1;
560:     y[4*i+1] = sum2;
561:     y[4*i+2] = sum3;
562:     y[4*i+3] = sum4;
563:   }

565:   PetscLogFlops(8.0*a->nz - 4.0*nonzerorow);
566:   VecRestoreArrayRead(xx,&x);
567:   VecRestoreArray(yy,&y);
568:   return(0);
569: }

573: PetscErrorCode MatMultTranspose_SeqMAIJ_4(Mat A,Vec xx,Vec yy)
574: {
575:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
576:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
577:   const PetscScalar *x,*v;
578:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4;
579:   PetscErrorCode    ierr;
580:   PetscInt          n,i;
581:   const PetscInt    m = b->AIJ->rmap->n,*idx;

584:   VecSet(yy,0.0);
585:   VecGetArrayRead(xx,&x);
586:   VecGetArray(yy,&y);
587:   for (i=0; i<m; i++) {
588:     idx    = a->j + a->i[i];
589:     v      = a->a + a->i[i];
590:     n      = a->i[i+1] - a->i[i];
591:     alpha1 = x[4*i];
592:     alpha2 = x[4*i+1];
593:     alpha3 = x[4*i+2];
594:     alpha4 = x[4*i+3];
595:     while (n-->0) {
596:       y[4*(*idx)]   += alpha1*(*v);
597:       y[4*(*idx)+1] += alpha2*(*v);
598:       y[4*(*idx)+2] += alpha3*(*v);
599:       y[4*(*idx)+3] += alpha4*(*v);
600:       idx++; v++;
601:     }
602:   }
603:   PetscLogFlops(8.0*a->nz);
604:   VecRestoreArrayRead(xx,&x);
605:   VecRestoreArray(yy,&y);
606:   return(0);
607: }

611: PetscErrorCode MatMultAdd_SeqMAIJ_4(Mat A,Vec xx,Vec yy,Vec zz)
612: {
613:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
614:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
615:   const PetscScalar *x,*v;
616:   PetscScalar       *y,sum1, sum2, sum3, sum4;
617:   PetscErrorCode    ierr;
618:   PetscInt          n,i,jrow,j;
619:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;

622:   if (yy != zz) {VecCopy(yy,zz);}
623:   VecGetArrayRead(xx,&x);
624:   VecGetArray(zz,&y);
625:   idx  = a->j;
626:   v    = a->a;
627:   ii   = a->i;

629:   for (i=0; i<m; i++) {
630:     jrow = ii[i];
631:     n    = ii[i+1] - jrow;
632:     sum1 = 0.0;
633:     sum2 = 0.0;
634:     sum3 = 0.0;
635:     sum4 = 0.0;
636:     for (j=0; j<n; j++) {
637:       sum1 += v[jrow]*x[4*idx[jrow]];
638:       sum2 += v[jrow]*x[4*idx[jrow]+1];
639:       sum3 += v[jrow]*x[4*idx[jrow]+2];
640:       sum4 += v[jrow]*x[4*idx[jrow]+3];
641:       jrow++;
642:     }
643:     y[4*i]   += sum1;
644:     y[4*i+1] += sum2;
645:     y[4*i+2] += sum3;
646:     y[4*i+3] += sum4;
647:   }

649:   PetscLogFlops(8.0*a->nz);
650:   VecRestoreArrayRead(xx,&x);
651:   VecRestoreArray(zz,&y);
652:   return(0);
653: }
656: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_4(Mat A,Vec xx,Vec yy,Vec zz)
657: {
658:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
659:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
660:   const PetscScalar *x,*v;
661:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4;
662:   PetscErrorCode    ierr;
663:   PetscInt          n,i;
664:   const PetscInt    m = b->AIJ->rmap->n,*idx;

667:   if (yy != zz) {VecCopy(yy,zz);}
668:   VecGetArrayRead(xx,&x);
669:   VecGetArray(zz,&y);

671:   for (i=0; i<m; i++) {
672:     idx    = a->j + a->i[i];
673:     v      = a->a + a->i[i];
674:     n      = a->i[i+1] - a->i[i];
675:     alpha1 = x[4*i];
676:     alpha2 = x[4*i+1];
677:     alpha3 = x[4*i+2];
678:     alpha4 = x[4*i+3];
679:     while (n-->0) {
680:       y[4*(*idx)]   += alpha1*(*v);
681:       y[4*(*idx)+1] += alpha2*(*v);
682:       y[4*(*idx)+2] += alpha3*(*v);
683:       y[4*(*idx)+3] += alpha4*(*v);
684:       idx++; v++;
685:     }
686:   }
687:   PetscLogFlops(8.0*a->nz);
688:   VecRestoreArrayRead(xx,&x);
689:   VecRestoreArray(zz,&y);
690:   return(0);
691: }
692: /* ------------------------------------------------------------------------------*/

696: PetscErrorCode MatMult_SeqMAIJ_5(Mat A,Vec xx,Vec yy)
697: {
698:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
699:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
700:   const PetscScalar *x,*v;
701:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5;
702:   PetscErrorCode    ierr;
703:   PetscInt          nonzerorow=0,n,i,jrow,j;
704:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;

707:   VecGetArrayRead(xx,&x);
708:   VecGetArray(yy,&y);
709:   idx  = a->j;
710:   v    = a->a;
711:   ii   = a->i;

713:   for (i=0; i<m; i++) {
714:     jrow  = ii[i];
715:     n     = ii[i+1] - jrow;
716:     sum1  = 0.0;
717:     sum2  = 0.0;
718:     sum3  = 0.0;
719:     sum4  = 0.0;
720:     sum5  = 0.0;

722:     nonzerorow += (n>0);
723:     for (j=0; j<n; j++) {
724:       sum1 += v[jrow]*x[5*idx[jrow]];
725:       sum2 += v[jrow]*x[5*idx[jrow]+1];
726:       sum3 += v[jrow]*x[5*idx[jrow]+2];
727:       sum4 += v[jrow]*x[5*idx[jrow]+3];
728:       sum5 += v[jrow]*x[5*idx[jrow]+4];
729:       jrow++;
730:     }
731:     y[5*i]   = sum1;
732:     y[5*i+1] = sum2;
733:     y[5*i+2] = sum3;
734:     y[5*i+3] = sum4;
735:     y[5*i+4] = sum5;
736:   }

738:   PetscLogFlops(10.0*a->nz - 5.0*nonzerorow);
739:   VecRestoreArrayRead(xx,&x);
740:   VecRestoreArray(yy,&y);
741:   return(0);
742: }

746: PetscErrorCode MatMultTranspose_SeqMAIJ_5(Mat A,Vec xx,Vec yy)
747: {
748:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
749:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
750:   const PetscScalar *x,*v;
751:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5;
752:   PetscErrorCode    ierr;
753:   PetscInt          n,i;
754:   const PetscInt    m = b->AIJ->rmap->n,*idx;

757:   VecSet(yy,0.0);
758:   VecGetArrayRead(xx,&x);
759:   VecGetArray(yy,&y);

761:   for (i=0; i<m; i++) {
762:     idx    = a->j + a->i[i];
763:     v      = a->a + a->i[i];
764:     n      = a->i[i+1] - a->i[i];
765:     alpha1 = x[5*i];
766:     alpha2 = x[5*i+1];
767:     alpha3 = x[5*i+2];
768:     alpha4 = x[5*i+3];
769:     alpha5 = x[5*i+4];
770:     while (n-->0) {
771:       y[5*(*idx)]   += alpha1*(*v);
772:       y[5*(*idx)+1] += alpha2*(*v);
773:       y[5*(*idx)+2] += alpha3*(*v);
774:       y[5*(*idx)+3] += alpha4*(*v);
775:       y[5*(*idx)+4] += alpha5*(*v);
776:       idx++; v++;
777:     }
778:   }
779:   PetscLogFlops(10.0*a->nz);
780:   VecRestoreArrayRead(xx,&x);
781:   VecRestoreArray(yy,&y);
782:   return(0);
783: }

787: PetscErrorCode MatMultAdd_SeqMAIJ_5(Mat A,Vec xx,Vec yy,Vec zz)
788: {
789:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
790:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
791:   const PetscScalar *x,*v;
792:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5;
793:   PetscErrorCode    ierr;
794:   PetscInt          n,i,jrow,j;
795:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;

798:   if (yy != zz) {VecCopy(yy,zz);}
799:   VecGetArrayRead(xx,&x);
800:   VecGetArray(zz,&y);
801:   idx  = a->j;
802:   v    = a->a;
803:   ii   = a->i;

805:   for (i=0; i<m; i++) {
806:     jrow = ii[i];
807:     n    = ii[i+1] - jrow;
808:     sum1 = 0.0;
809:     sum2 = 0.0;
810:     sum3 = 0.0;
811:     sum4 = 0.0;
812:     sum5 = 0.0;
813:     for (j=0; j<n; j++) {
814:       sum1 += v[jrow]*x[5*idx[jrow]];
815:       sum2 += v[jrow]*x[5*idx[jrow]+1];
816:       sum3 += v[jrow]*x[5*idx[jrow]+2];
817:       sum4 += v[jrow]*x[5*idx[jrow]+3];
818:       sum5 += v[jrow]*x[5*idx[jrow]+4];
819:       jrow++;
820:     }
821:     y[5*i]   += sum1;
822:     y[5*i+1] += sum2;
823:     y[5*i+2] += sum3;
824:     y[5*i+3] += sum4;
825:     y[5*i+4] += sum5;
826:   }

828:   PetscLogFlops(10.0*a->nz);
829:   VecRestoreArrayRead(xx,&x);
830:   VecRestoreArray(zz,&y);
831:   return(0);
832: }

836: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_5(Mat A,Vec xx,Vec yy,Vec zz)
837: {
838:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
839:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
840:   const PetscScalar *x,*v;
841:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5;
842:   PetscErrorCode    ierr;
843:   PetscInt          n,i;
844:   const PetscInt    m = b->AIJ->rmap->n,*idx;

847:   if (yy != zz) {VecCopy(yy,zz);}
848:   VecGetArrayRead(xx,&x);
849:   VecGetArray(zz,&y);

851:   for (i=0; i<m; i++) {
852:     idx    = a->j + a->i[i];
853:     v      = a->a + a->i[i];
854:     n      = a->i[i+1] - a->i[i];
855:     alpha1 = x[5*i];
856:     alpha2 = x[5*i+1];
857:     alpha3 = x[5*i+2];
858:     alpha4 = x[5*i+3];
859:     alpha5 = x[5*i+4];
860:     while (n-->0) {
861:       y[5*(*idx)]   += alpha1*(*v);
862:       y[5*(*idx)+1] += alpha2*(*v);
863:       y[5*(*idx)+2] += alpha3*(*v);
864:       y[5*(*idx)+3] += alpha4*(*v);
865:       y[5*(*idx)+4] += alpha5*(*v);
866:       idx++; v++;
867:     }
868:   }
869:   PetscLogFlops(10.0*a->nz);
870:   VecRestoreArrayRead(xx,&x);
871:   VecRestoreArray(zz,&y);
872:   return(0);
873: }

875: /* ------------------------------------------------------------------------------*/
878: PetscErrorCode MatMult_SeqMAIJ_6(Mat A,Vec xx,Vec yy)
879: {
880:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
881:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
882:   const PetscScalar *x,*v;
883:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6;
884:   PetscErrorCode    ierr;
885:   PetscInt          nonzerorow=0,n,i,jrow,j;
886:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;

889:   VecGetArrayRead(xx,&x);
890:   VecGetArray(yy,&y);
891:   idx  = a->j;
892:   v    = a->a;
893:   ii   = a->i;

895:   for (i=0; i<m; i++) {
896:     jrow  = ii[i];
897:     n     = ii[i+1] - jrow;
898:     sum1  = 0.0;
899:     sum2  = 0.0;
900:     sum3  = 0.0;
901:     sum4  = 0.0;
902:     sum5  = 0.0;
903:     sum6  = 0.0;

905:     nonzerorow += (n>0);
906:     for (j=0; j<n; j++) {
907:       sum1 += v[jrow]*x[6*idx[jrow]];
908:       sum2 += v[jrow]*x[6*idx[jrow]+1];
909:       sum3 += v[jrow]*x[6*idx[jrow]+2];
910:       sum4 += v[jrow]*x[6*idx[jrow]+3];
911:       sum5 += v[jrow]*x[6*idx[jrow]+4];
912:       sum6 += v[jrow]*x[6*idx[jrow]+5];
913:       jrow++;
914:     }
915:     y[6*i]   = sum1;
916:     y[6*i+1] = sum2;
917:     y[6*i+2] = sum3;
918:     y[6*i+3] = sum4;
919:     y[6*i+4] = sum5;
920:     y[6*i+5] = sum6;
921:   }

923:   PetscLogFlops(12.0*a->nz - 6.0*nonzerorow);
924:   VecRestoreArrayRead(xx,&x);
925:   VecRestoreArray(yy,&y);
926:   return(0);
927: }

931: PetscErrorCode MatMultTranspose_SeqMAIJ_6(Mat A,Vec xx,Vec yy)
932: {
933:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
934:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
935:   const PetscScalar *x,*v;
936:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6;
937:   PetscErrorCode    ierr;
938:   PetscInt          n,i;
939:   const PetscInt    m = b->AIJ->rmap->n,*idx;

942:   VecSet(yy,0.0);
943:   VecGetArrayRead(xx,&x);
944:   VecGetArray(yy,&y);

946:   for (i=0; i<m; i++) {
947:     idx    = a->j + a->i[i];
948:     v      = a->a + a->i[i];
949:     n      = a->i[i+1] - a->i[i];
950:     alpha1 = x[6*i];
951:     alpha2 = x[6*i+1];
952:     alpha3 = x[6*i+2];
953:     alpha4 = x[6*i+3];
954:     alpha5 = x[6*i+4];
955:     alpha6 = x[6*i+5];
956:     while (n-->0) {
957:       y[6*(*idx)]   += alpha1*(*v);
958:       y[6*(*idx)+1] += alpha2*(*v);
959:       y[6*(*idx)+2] += alpha3*(*v);
960:       y[6*(*idx)+3] += alpha4*(*v);
961:       y[6*(*idx)+4] += alpha5*(*v);
962:       y[6*(*idx)+5] += alpha6*(*v);
963:       idx++; v++;
964:     }
965:   }
966:   PetscLogFlops(12.0*a->nz);
967:   VecRestoreArrayRead(xx,&x);
968:   VecRestoreArray(yy,&y);
969:   return(0);
970: }

974: PetscErrorCode MatMultAdd_SeqMAIJ_6(Mat A,Vec xx,Vec yy,Vec zz)
975: {
976:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
977:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
978:   const PetscScalar *x,*v;
979:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6;
980:   PetscErrorCode    ierr;
981:   PetscInt          n,i,jrow,j;
982:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;

985:   if (yy != zz) {VecCopy(yy,zz);}
986:   VecGetArrayRead(xx,&x);
987:   VecGetArray(zz,&y);
988:   idx  = a->j;
989:   v    = a->a;
990:   ii   = a->i;

992:   for (i=0; i<m; i++) {
993:     jrow = ii[i];
994:     n    = ii[i+1] - jrow;
995:     sum1 = 0.0;
996:     sum2 = 0.0;
997:     sum3 = 0.0;
998:     sum4 = 0.0;
999:     sum5 = 0.0;
1000:     sum6 = 0.0;
1001:     for (j=0; j<n; j++) {
1002:       sum1 += v[jrow]*x[6*idx[jrow]];
1003:       sum2 += v[jrow]*x[6*idx[jrow]+1];
1004:       sum3 += v[jrow]*x[6*idx[jrow]+2];
1005:       sum4 += v[jrow]*x[6*idx[jrow]+3];
1006:       sum5 += v[jrow]*x[6*idx[jrow]+4];
1007:       sum6 += v[jrow]*x[6*idx[jrow]+5];
1008:       jrow++;
1009:     }
1010:     y[6*i]   += sum1;
1011:     y[6*i+1] += sum2;
1012:     y[6*i+2] += sum3;
1013:     y[6*i+3] += sum4;
1014:     y[6*i+4] += sum5;
1015:     y[6*i+5] += sum6;
1016:   }

1018:   PetscLogFlops(12.0*a->nz);
1019:   VecRestoreArrayRead(xx,&x);
1020:   VecRestoreArray(zz,&y);
1021:   return(0);
1022: }

1026: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_6(Mat A,Vec xx,Vec yy,Vec zz)
1027: {
1028:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1029:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1030:   const PetscScalar *x,*v;
1031:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6;
1032:   PetscErrorCode    ierr;
1033:   PetscInt          n,i;
1034:   const PetscInt    m = b->AIJ->rmap->n,*idx;

1037:   if (yy != zz) {VecCopy(yy,zz);}
1038:   VecGetArrayRead(xx,&x);
1039:   VecGetArray(zz,&y);

1041:   for (i=0; i<m; i++) {
1042:     idx    = a->j + a->i[i];
1043:     v      = a->a + a->i[i];
1044:     n      = a->i[i+1] - a->i[i];
1045:     alpha1 = x[6*i];
1046:     alpha2 = x[6*i+1];
1047:     alpha3 = x[6*i+2];
1048:     alpha4 = x[6*i+3];
1049:     alpha5 = x[6*i+4];
1050:     alpha6 = x[6*i+5];
1051:     while (n-->0) {
1052:       y[6*(*idx)]   += alpha1*(*v);
1053:       y[6*(*idx)+1] += alpha2*(*v);
1054:       y[6*(*idx)+2] += alpha3*(*v);
1055:       y[6*(*idx)+3] += alpha4*(*v);
1056:       y[6*(*idx)+4] += alpha5*(*v);
1057:       y[6*(*idx)+5] += alpha6*(*v);
1058:       idx++; v++;
1059:     }
1060:   }
1061:   PetscLogFlops(12.0*a->nz);
1062:   VecRestoreArrayRead(xx,&x);
1063:   VecRestoreArray(zz,&y);
1064:   return(0);
1065: }

1067: /* ------------------------------------------------------------------------------*/
1070: PetscErrorCode MatMult_SeqMAIJ_7(Mat A,Vec xx,Vec yy)
1071: {
1072:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1073:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1074:   const PetscScalar *x,*v;
1075:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7;
1076:   PetscErrorCode    ierr;
1077:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
1078:   PetscInt          nonzerorow=0,n,i,jrow,j;

1081:   VecGetArrayRead(xx,&x);
1082:   VecGetArray(yy,&y);
1083:   idx  = a->j;
1084:   v    = a->a;
1085:   ii   = a->i;

1087:   for (i=0; i<m; i++) {
1088:     jrow  = ii[i];
1089:     n     = ii[i+1] - jrow;
1090:     sum1  = 0.0;
1091:     sum2  = 0.0;
1092:     sum3  = 0.0;
1093:     sum4  = 0.0;
1094:     sum5  = 0.0;
1095:     sum6  = 0.0;
1096:     sum7  = 0.0;

1098:     nonzerorow += (n>0);
1099:     for (j=0; j<n; j++) {
1100:       sum1 += v[jrow]*x[7*idx[jrow]];
1101:       sum2 += v[jrow]*x[7*idx[jrow]+1];
1102:       sum3 += v[jrow]*x[7*idx[jrow]+2];
1103:       sum4 += v[jrow]*x[7*idx[jrow]+3];
1104:       sum5 += v[jrow]*x[7*idx[jrow]+4];
1105:       sum6 += v[jrow]*x[7*idx[jrow]+5];
1106:       sum7 += v[jrow]*x[7*idx[jrow]+6];
1107:       jrow++;
1108:     }
1109:     y[7*i]   = sum1;
1110:     y[7*i+1] = sum2;
1111:     y[7*i+2] = sum3;
1112:     y[7*i+3] = sum4;
1113:     y[7*i+4] = sum5;
1114:     y[7*i+5] = sum6;
1115:     y[7*i+6] = sum7;
1116:   }

1118:   PetscLogFlops(14.0*a->nz - 7.0*nonzerorow);
1119:   VecRestoreArrayRead(xx,&x);
1120:   VecRestoreArray(yy,&y);
1121:   return(0);
1122: }

1126: PetscErrorCode MatMultTranspose_SeqMAIJ_7(Mat A,Vec xx,Vec yy)
1127: {
1128:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1129:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1130:   const PetscScalar *x,*v;
1131:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7;
1132:   PetscErrorCode    ierr;
1133:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1134:   PetscInt          n,i;

1137:   VecSet(yy,0.0);
1138:   VecGetArrayRead(xx,&x);
1139:   VecGetArray(yy,&y);

1141:   for (i=0; i<m; i++) {
1142:     idx    = a->j + a->i[i];
1143:     v      = a->a + a->i[i];
1144:     n      = a->i[i+1] - a->i[i];
1145:     alpha1 = x[7*i];
1146:     alpha2 = x[7*i+1];
1147:     alpha3 = x[7*i+2];
1148:     alpha4 = x[7*i+3];
1149:     alpha5 = x[7*i+4];
1150:     alpha6 = x[7*i+5];
1151:     alpha7 = x[7*i+6];
1152:     while (n-->0) {
1153:       y[7*(*idx)]   += alpha1*(*v);
1154:       y[7*(*idx)+1] += alpha2*(*v);
1155:       y[7*(*idx)+2] += alpha3*(*v);
1156:       y[7*(*idx)+3] += alpha4*(*v);
1157:       y[7*(*idx)+4] += alpha5*(*v);
1158:       y[7*(*idx)+5] += alpha6*(*v);
1159:       y[7*(*idx)+6] += alpha7*(*v);
1160:       idx++; v++;
1161:     }
1162:   }
1163:   PetscLogFlops(14.0*a->nz);
1164:   VecRestoreArrayRead(xx,&x);
1165:   VecRestoreArray(yy,&y);
1166:   return(0);
1167: }

1171: PetscErrorCode MatMultAdd_SeqMAIJ_7(Mat A,Vec xx,Vec yy,Vec zz)
1172: {
1173:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1174:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1175:   const PetscScalar *x,*v;
1176:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7;
1177:   PetscErrorCode    ierr;
1178:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
1179:   PetscInt          n,i,jrow,j;

1182:   if (yy != zz) {VecCopy(yy,zz);}
1183:   VecGetArrayRead(xx,&x);
1184:   VecGetArray(zz,&y);
1185:   idx  = a->j;
1186:   v    = a->a;
1187:   ii   = a->i;

1189:   for (i=0; i<m; i++) {
1190:     jrow = ii[i];
1191:     n    = ii[i+1] - jrow;
1192:     sum1 = 0.0;
1193:     sum2 = 0.0;
1194:     sum3 = 0.0;
1195:     sum4 = 0.0;
1196:     sum5 = 0.0;
1197:     sum6 = 0.0;
1198:     sum7 = 0.0;
1199:     for (j=0; j<n; j++) {
1200:       sum1 += v[jrow]*x[7*idx[jrow]];
1201:       sum2 += v[jrow]*x[7*idx[jrow]+1];
1202:       sum3 += v[jrow]*x[7*idx[jrow]+2];
1203:       sum4 += v[jrow]*x[7*idx[jrow]+3];
1204:       sum5 += v[jrow]*x[7*idx[jrow]+4];
1205:       sum6 += v[jrow]*x[7*idx[jrow]+5];
1206:       sum7 += v[jrow]*x[7*idx[jrow]+6];
1207:       jrow++;
1208:     }
1209:     y[7*i]   += sum1;
1210:     y[7*i+1] += sum2;
1211:     y[7*i+2] += sum3;
1212:     y[7*i+3] += sum4;
1213:     y[7*i+4] += sum5;
1214:     y[7*i+5] += sum6;
1215:     y[7*i+6] += sum7;
1216:   }

1218:   PetscLogFlops(14.0*a->nz);
1219:   VecRestoreArrayRead(xx,&x);
1220:   VecRestoreArray(zz,&y);
1221:   return(0);
1222: }

1226: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_7(Mat A,Vec xx,Vec yy,Vec zz)
1227: {
1228:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1229:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1230:   const PetscScalar *x,*v;
1231:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7;
1232:   PetscErrorCode    ierr;
1233:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1234:   PetscInt          n,i;

1237:   if (yy != zz) {VecCopy(yy,zz);}
1238:   VecGetArrayRead(xx,&x);
1239:   VecGetArray(zz,&y);
1240:   for (i=0; i<m; i++) {
1241:     idx    = a->j + a->i[i];
1242:     v      = a->a + a->i[i];
1243:     n      = a->i[i+1] - a->i[i];
1244:     alpha1 = x[7*i];
1245:     alpha2 = x[7*i+1];
1246:     alpha3 = x[7*i+2];
1247:     alpha4 = x[7*i+3];
1248:     alpha5 = x[7*i+4];
1249:     alpha6 = x[7*i+5];
1250:     alpha7 = x[7*i+6];
1251:     while (n-->0) {
1252:       y[7*(*idx)]   += alpha1*(*v);
1253:       y[7*(*idx)+1] += alpha2*(*v);
1254:       y[7*(*idx)+2] += alpha3*(*v);
1255:       y[7*(*idx)+3] += alpha4*(*v);
1256:       y[7*(*idx)+4] += alpha5*(*v);
1257:       y[7*(*idx)+5] += alpha6*(*v);
1258:       y[7*(*idx)+6] += alpha7*(*v);
1259:       idx++; v++;
1260:     }
1261:   }
1262:   PetscLogFlops(14.0*a->nz);
1263:   VecRestoreArrayRead(xx,&x);
1264:   VecRestoreArray(zz,&y);
1265:   return(0);
1266: }

1270: PetscErrorCode MatMult_SeqMAIJ_8(Mat A,Vec xx,Vec yy)
1271: {
1272:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1273:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1274:   const PetscScalar *x,*v;
1275:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
1276:   PetscErrorCode    ierr;
1277:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
1278:   PetscInt          nonzerorow=0,n,i,jrow,j;

1281:   VecGetArrayRead(xx,&x);
1282:   VecGetArray(yy,&y);
1283:   idx  = a->j;
1284:   v    = a->a;
1285:   ii   = a->i;

1287:   for (i=0; i<m; i++) {
1288:     jrow  = ii[i];
1289:     n     = ii[i+1] - jrow;
1290:     sum1  = 0.0;
1291:     sum2  = 0.0;
1292:     sum3  = 0.0;
1293:     sum4  = 0.0;
1294:     sum5  = 0.0;
1295:     sum6  = 0.0;
1296:     sum7  = 0.0;
1297:     sum8  = 0.0;

1299:     nonzerorow += (n>0);
1300:     for (j=0; j<n; j++) {
1301:       sum1 += v[jrow]*x[8*idx[jrow]];
1302:       sum2 += v[jrow]*x[8*idx[jrow]+1];
1303:       sum3 += v[jrow]*x[8*idx[jrow]+2];
1304:       sum4 += v[jrow]*x[8*idx[jrow]+3];
1305:       sum5 += v[jrow]*x[8*idx[jrow]+4];
1306:       sum6 += v[jrow]*x[8*idx[jrow]+5];
1307:       sum7 += v[jrow]*x[8*idx[jrow]+6];
1308:       sum8 += v[jrow]*x[8*idx[jrow]+7];
1309:       jrow++;
1310:     }
1311:     y[8*i]   = sum1;
1312:     y[8*i+1] = sum2;
1313:     y[8*i+2] = sum3;
1314:     y[8*i+3] = sum4;
1315:     y[8*i+4] = sum5;
1316:     y[8*i+5] = sum6;
1317:     y[8*i+6] = sum7;
1318:     y[8*i+7] = sum8;
1319:   }

1321:   PetscLogFlops(16.0*a->nz - 8.0*nonzerorow);
1322:   VecRestoreArrayRead(xx,&x);
1323:   VecRestoreArray(yy,&y);
1324:   return(0);
1325: }

1329: PetscErrorCode MatMultTranspose_SeqMAIJ_8(Mat A,Vec xx,Vec yy)
1330: {
1331:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1332:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1333:   const PetscScalar *x,*v;
1334:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
1335:   PetscErrorCode    ierr;
1336:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1337:   PetscInt          n,i;

1340:   VecSet(yy,0.0);
1341:   VecGetArrayRead(xx,&x);
1342:   VecGetArray(yy,&y);

1344:   for (i=0; i<m; i++) {
1345:     idx    = a->j + a->i[i];
1346:     v      = a->a + a->i[i];
1347:     n      = a->i[i+1] - a->i[i];
1348:     alpha1 = x[8*i];
1349:     alpha2 = x[8*i+1];
1350:     alpha3 = x[8*i+2];
1351:     alpha4 = x[8*i+3];
1352:     alpha5 = x[8*i+4];
1353:     alpha6 = x[8*i+5];
1354:     alpha7 = x[8*i+6];
1355:     alpha8 = x[8*i+7];
1356:     while (n-->0) {
1357:       y[8*(*idx)]   += alpha1*(*v);
1358:       y[8*(*idx)+1] += alpha2*(*v);
1359:       y[8*(*idx)+2] += alpha3*(*v);
1360:       y[8*(*idx)+3] += alpha4*(*v);
1361:       y[8*(*idx)+4] += alpha5*(*v);
1362:       y[8*(*idx)+5] += alpha6*(*v);
1363:       y[8*(*idx)+6] += alpha7*(*v);
1364:       y[8*(*idx)+7] += alpha8*(*v);
1365:       idx++; v++;
1366:     }
1367:   }
1368:   PetscLogFlops(16.0*a->nz);
1369:   VecRestoreArrayRead(xx,&x);
1370:   VecRestoreArray(yy,&y);
1371:   return(0);
1372: }

1376: PetscErrorCode MatMultAdd_SeqMAIJ_8(Mat A,Vec xx,Vec yy,Vec zz)
1377: {
1378:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1379:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1380:   const PetscScalar *x,*v;
1381:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
1382:   PetscErrorCode    ierr;
1383:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
1384:   PetscInt          n,i,jrow,j;

1387:   if (yy != zz) {VecCopy(yy,zz);}
1388:   VecGetArrayRead(xx,&x);
1389:   VecGetArray(zz,&y);
1390:   idx  = a->j;
1391:   v    = a->a;
1392:   ii   = a->i;

1394:   for (i=0; i<m; i++) {
1395:     jrow = ii[i];
1396:     n    = ii[i+1] - jrow;
1397:     sum1 = 0.0;
1398:     sum2 = 0.0;
1399:     sum3 = 0.0;
1400:     sum4 = 0.0;
1401:     sum5 = 0.0;
1402:     sum6 = 0.0;
1403:     sum7 = 0.0;
1404:     sum8 = 0.0;
1405:     for (j=0; j<n; j++) {
1406:       sum1 += v[jrow]*x[8*idx[jrow]];
1407:       sum2 += v[jrow]*x[8*idx[jrow]+1];
1408:       sum3 += v[jrow]*x[8*idx[jrow]+2];
1409:       sum4 += v[jrow]*x[8*idx[jrow]+3];
1410:       sum5 += v[jrow]*x[8*idx[jrow]+4];
1411:       sum6 += v[jrow]*x[8*idx[jrow]+5];
1412:       sum7 += v[jrow]*x[8*idx[jrow]+6];
1413:       sum8 += v[jrow]*x[8*idx[jrow]+7];
1414:       jrow++;
1415:     }
1416:     y[8*i]   += sum1;
1417:     y[8*i+1] += sum2;
1418:     y[8*i+2] += sum3;
1419:     y[8*i+3] += sum4;
1420:     y[8*i+4] += sum5;
1421:     y[8*i+5] += sum6;
1422:     y[8*i+6] += sum7;
1423:     y[8*i+7] += sum8;
1424:   }

1426:   PetscLogFlops(16.0*a->nz);
1427:   VecRestoreArrayRead(xx,&x);
1428:   VecRestoreArray(zz,&y);
1429:   return(0);
1430: }

1434: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_8(Mat A,Vec xx,Vec yy,Vec zz)
1435: {
1436:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1437:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1438:   const PetscScalar *x,*v;
1439:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
1440:   PetscErrorCode    ierr;
1441:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1442:   PetscInt          n,i;

1445:   if (yy != zz) {VecCopy(yy,zz);}
1446:   VecGetArrayRead(xx,&x);
1447:   VecGetArray(zz,&y);
1448:   for (i=0; i<m; i++) {
1449:     idx    = a->j + a->i[i];
1450:     v      = a->a + a->i[i];
1451:     n      = a->i[i+1] - a->i[i];
1452:     alpha1 = x[8*i];
1453:     alpha2 = x[8*i+1];
1454:     alpha3 = x[8*i+2];
1455:     alpha4 = x[8*i+3];
1456:     alpha5 = x[8*i+4];
1457:     alpha6 = x[8*i+5];
1458:     alpha7 = x[8*i+6];
1459:     alpha8 = x[8*i+7];
1460:     while (n-->0) {
1461:       y[8*(*idx)]   += alpha1*(*v);
1462:       y[8*(*idx)+1] += alpha2*(*v);
1463:       y[8*(*idx)+2] += alpha3*(*v);
1464:       y[8*(*idx)+3] += alpha4*(*v);
1465:       y[8*(*idx)+4] += alpha5*(*v);
1466:       y[8*(*idx)+5] += alpha6*(*v);
1467:       y[8*(*idx)+6] += alpha7*(*v);
1468:       y[8*(*idx)+7] += alpha8*(*v);
1469:       idx++; v++;
1470:     }
1471:   }
1472:   PetscLogFlops(16.0*a->nz);
1473:   VecRestoreArrayRead(xx,&x);
1474:   VecRestoreArray(zz,&y);
1475:   return(0);
1476: }

1478: /* ------------------------------------------------------------------------------*/
1481: PetscErrorCode MatMult_SeqMAIJ_9(Mat A,Vec xx,Vec yy)
1482: {
1483:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1484:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1485:   const PetscScalar *x,*v;
1486:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9;
1487:   PetscErrorCode    ierr;
1488:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
1489:   PetscInt          nonzerorow=0,n,i,jrow,j;

1492:   VecGetArrayRead(xx,&x);
1493:   VecGetArray(yy,&y);
1494:   idx  = a->j;
1495:   v    = a->a;
1496:   ii   = a->i;

1498:   for (i=0; i<m; i++) {
1499:     jrow  = ii[i];
1500:     n     = ii[i+1] - jrow;
1501:     sum1  = 0.0;
1502:     sum2  = 0.0;
1503:     sum3  = 0.0;
1504:     sum4  = 0.0;
1505:     sum5  = 0.0;
1506:     sum6  = 0.0;
1507:     sum7  = 0.0;
1508:     sum8  = 0.0;
1509:     sum9  = 0.0;

1511:     nonzerorow += (n>0);
1512:     for (j=0; j<n; j++) {
1513:       sum1 += v[jrow]*x[9*idx[jrow]];
1514:       sum2 += v[jrow]*x[9*idx[jrow]+1];
1515:       sum3 += v[jrow]*x[9*idx[jrow]+2];
1516:       sum4 += v[jrow]*x[9*idx[jrow]+3];
1517:       sum5 += v[jrow]*x[9*idx[jrow]+4];
1518:       sum6 += v[jrow]*x[9*idx[jrow]+5];
1519:       sum7 += v[jrow]*x[9*idx[jrow]+6];
1520:       sum8 += v[jrow]*x[9*idx[jrow]+7];
1521:       sum9 += v[jrow]*x[9*idx[jrow]+8];
1522:       jrow++;
1523:     }
1524:     y[9*i]   = sum1;
1525:     y[9*i+1] = sum2;
1526:     y[9*i+2] = sum3;
1527:     y[9*i+3] = sum4;
1528:     y[9*i+4] = sum5;
1529:     y[9*i+5] = sum6;
1530:     y[9*i+6] = sum7;
1531:     y[9*i+7] = sum8;
1532:     y[9*i+8] = sum9;
1533:   }

1535:   PetscLogFlops(18.0*a->nz - 9*nonzerorow);
1536:   VecRestoreArrayRead(xx,&x);
1537:   VecRestoreArray(yy,&y);
1538:   return(0);
1539: }

1541: /* ------------------------------------------------------------------------------*/

1545: PetscErrorCode MatMultTranspose_SeqMAIJ_9(Mat A,Vec xx,Vec yy)
1546: {
1547:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1548:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1549:   const PetscScalar *x,*v;
1550:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9;
1551:   PetscErrorCode    ierr;
1552:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1553:   PetscInt          n,i;

1556:   VecSet(yy,0.0);
1557:   VecGetArrayRead(xx,&x);
1558:   VecGetArray(yy,&y);

1560:   for (i=0; i<m; i++) {
1561:     idx    = a->j + a->i[i];
1562:     v      = a->a + a->i[i];
1563:     n      = a->i[i+1] - a->i[i];
1564:     alpha1 = x[9*i];
1565:     alpha2 = x[9*i+1];
1566:     alpha3 = x[9*i+2];
1567:     alpha4 = x[9*i+3];
1568:     alpha5 = x[9*i+4];
1569:     alpha6 = x[9*i+5];
1570:     alpha7 = x[9*i+6];
1571:     alpha8 = x[9*i+7];
1572:     alpha9 = x[9*i+8];
1573:     while (n-->0) {
1574:       y[9*(*idx)]   += alpha1*(*v);
1575:       y[9*(*idx)+1] += alpha2*(*v);
1576:       y[9*(*idx)+2] += alpha3*(*v);
1577:       y[9*(*idx)+3] += alpha4*(*v);
1578:       y[9*(*idx)+4] += alpha5*(*v);
1579:       y[9*(*idx)+5] += alpha6*(*v);
1580:       y[9*(*idx)+6] += alpha7*(*v);
1581:       y[9*(*idx)+7] += alpha8*(*v);
1582:       y[9*(*idx)+8] += alpha9*(*v);
1583:       idx++; v++;
1584:     }
1585:   }
1586:   PetscLogFlops(18.0*a->nz);
1587:   VecRestoreArrayRead(xx,&x);
1588:   VecRestoreArray(yy,&y);
1589:   return(0);
1590: }

1594: PetscErrorCode MatMultAdd_SeqMAIJ_9(Mat A,Vec xx,Vec yy,Vec zz)
1595: {
1596:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1597:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1598:   const PetscScalar *x,*v;
1599:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9;
1600:   PetscErrorCode    ierr;
1601:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
1602:   PetscInt          n,i,jrow,j;

1605:   if (yy != zz) {VecCopy(yy,zz);}
1606:   VecGetArrayRead(xx,&x);
1607:   VecGetArray(zz,&y);
1608:   idx  = a->j;
1609:   v    = a->a;
1610:   ii   = a->i;

1612:   for (i=0; i<m; i++) {
1613:     jrow = ii[i];
1614:     n    = ii[i+1] - jrow;
1615:     sum1 = 0.0;
1616:     sum2 = 0.0;
1617:     sum3 = 0.0;
1618:     sum4 = 0.0;
1619:     sum5 = 0.0;
1620:     sum6 = 0.0;
1621:     sum7 = 0.0;
1622:     sum8 = 0.0;
1623:     sum9 = 0.0;
1624:     for (j=0; j<n; j++) {
1625:       sum1 += v[jrow]*x[9*idx[jrow]];
1626:       sum2 += v[jrow]*x[9*idx[jrow]+1];
1627:       sum3 += v[jrow]*x[9*idx[jrow]+2];
1628:       sum4 += v[jrow]*x[9*idx[jrow]+3];
1629:       sum5 += v[jrow]*x[9*idx[jrow]+4];
1630:       sum6 += v[jrow]*x[9*idx[jrow]+5];
1631:       sum7 += v[jrow]*x[9*idx[jrow]+6];
1632:       sum8 += v[jrow]*x[9*idx[jrow]+7];
1633:       sum9 += v[jrow]*x[9*idx[jrow]+8];
1634:       jrow++;
1635:     }
1636:     y[9*i]   += sum1;
1637:     y[9*i+1] += sum2;
1638:     y[9*i+2] += sum3;
1639:     y[9*i+3] += sum4;
1640:     y[9*i+4] += sum5;
1641:     y[9*i+5] += sum6;
1642:     y[9*i+6] += sum7;
1643:     y[9*i+7] += sum8;
1644:     y[9*i+8] += sum9;
1645:   }

1647:   PetscLogFlops(18*a->nz);
1648:   VecRestoreArrayRead(xx,&x);
1649:   VecRestoreArray(zz,&y);
1650:   return(0);
1651: }

1655: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_9(Mat A,Vec xx,Vec yy,Vec zz)
1656: {
1657:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1658:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1659:   const PetscScalar *x,*v;
1660:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9;
1661:   PetscErrorCode    ierr;
1662:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1663:   PetscInt          n,i;

1666:   if (yy != zz) {VecCopy(yy,zz);}
1667:   VecGetArrayRead(xx,&x);
1668:   VecGetArray(zz,&y);
1669:   for (i=0; i<m; i++) {
1670:     idx    = a->j + a->i[i];
1671:     v      = a->a + a->i[i];
1672:     n      = a->i[i+1] - a->i[i];
1673:     alpha1 = x[9*i];
1674:     alpha2 = x[9*i+1];
1675:     alpha3 = x[9*i+2];
1676:     alpha4 = x[9*i+3];
1677:     alpha5 = x[9*i+4];
1678:     alpha6 = x[9*i+5];
1679:     alpha7 = x[9*i+6];
1680:     alpha8 = x[9*i+7];
1681:     alpha9 = x[9*i+8];
1682:     while (n-->0) {
1683:       y[9*(*idx)]   += alpha1*(*v);
1684:       y[9*(*idx)+1] += alpha2*(*v);
1685:       y[9*(*idx)+2] += alpha3*(*v);
1686:       y[9*(*idx)+3] += alpha4*(*v);
1687:       y[9*(*idx)+4] += alpha5*(*v);
1688:       y[9*(*idx)+5] += alpha6*(*v);
1689:       y[9*(*idx)+6] += alpha7*(*v);
1690:       y[9*(*idx)+7] += alpha8*(*v);
1691:       y[9*(*idx)+8] += alpha9*(*v);
1692:       idx++; v++;
1693:     }
1694:   }
1695:   PetscLogFlops(18.0*a->nz);
1696:   VecRestoreArrayRead(xx,&x);
1697:   VecRestoreArray(zz,&y);
1698:   return(0);
1699: }
1702: PetscErrorCode MatMult_SeqMAIJ_10(Mat A,Vec xx,Vec yy)
1703: {
1704:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1705:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1706:   const PetscScalar *x,*v;
1707:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9, sum10;
1708:   PetscErrorCode    ierr;
1709:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
1710:   PetscInt          nonzerorow=0,n,i,jrow,j;

1713:   VecGetArrayRead(xx,&x);
1714:   VecGetArray(yy,&y);
1715:   idx  = a->j;
1716:   v    = a->a;
1717:   ii   = a->i;

1719:   for (i=0; i<m; i++) {
1720:     jrow  = ii[i];
1721:     n     = ii[i+1] - jrow;
1722:     sum1  = 0.0;
1723:     sum2  = 0.0;
1724:     sum3  = 0.0;
1725:     sum4  = 0.0;
1726:     sum5  = 0.0;
1727:     sum6  = 0.0;
1728:     sum7  = 0.0;
1729:     sum8  = 0.0;
1730:     sum9  = 0.0;
1731:     sum10 = 0.0;

1733:     nonzerorow += (n>0);
1734:     for (j=0; j<n; j++) {
1735:       sum1  += v[jrow]*x[10*idx[jrow]];
1736:       sum2  += v[jrow]*x[10*idx[jrow]+1];
1737:       sum3  += v[jrow]*x[10*idx[jrow]+2];
1738:       sum4  += v[jrow]*x[10*idx[jrow]+3];
1739:       sum5  += v[jrow]*x[10*idx[jrow]+4];
1740:       sum6  += v[jrow]*x[10*idx[jrow]+5];
1741:       sum7  += v[jrow]*x[10*idx[jrow]+6];
1742:       sum8  += v[jrow]*x[10*idx[jrow]+7];
1743:       sum9  += v[jrow]*x[10*idx[jrow]+8];
1744:       sum10 += v[jrow]*x[10*idx[jrow]+9];
1745:       jrow++;
1746:     }
1747:     y[10*i]   = sum1;
1748:     y[10*i+1] = sum2;
1749:     y[10*i+2] = sum3;
1750:     y[10*i+3] = sum4;
1751:     y[10*i+4] = sum5;
1752:     y[10*i+5] = sum6;
1753:     y[10*i+6] = sum7;
1754:     y[10*i+7] = sum8;
1755:     y[10*i+8] = sum9;
1756:     y[10*i+9] = sum10;
1757:   }

1759:   PetscLogFlops(20.0*a->nz - 10.0*nonzerorow);
1760:   VecRestoreArrayRead(xx,&x);
1761:   VecRestoreArray(yy,&y);
1762:   return(0);
1763: }

1767: PetscErrorCode MatMultAdd_SeqMAIJ_10(Mat A,Vec xx,Vec yy,Vec zz)
1768: {
1769:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1770:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1771:   const PetscScalar *x,*v;
1772:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9, sum10;
1773:   PetscErrorCode    ierr;
1774:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
1775:   PetscInt          n,i,jrow,j;

1778:   if (yy != zz) {VecCopy(yy,zz);}
1779:   VecGetArrayRead(xx,&x);
1780:   VecGetArray(zz,&y);
1781:   idx  = a->j;
1782:   v    = a->a;
1783:   ii   = a->i;

1785:   for (i=0; i<m; i++) {
1786:     jrow  = ii[i];
1787:     n     = ii[i+1] - jrow;
1788:     sum1  = 0.0;
1789:     sum2  = 0.0;
1790:     sum3  = 0.0;
1791:     sum4  = 0.0;
1792:     sum5  = 0.0;
1793:     sum6  = 0.0;
1794:     sum7  = 0.0;
1795:     sum8  = 0.0;
1796:     sum9  = 0.0;
1797:     sum10 = 0.0;
1798:     for (j=0; j<n; j++) {
1799:       sum1  += v[jrow]*x[10*idx[jrow]];
1800:       sum2  += v[jrow]*x[10*idx[jrow]+1];
1801:       sum3  += v[jrow]*x[10*idx[jrow]+2];
1802:       sum4  += v[jrow]*x[10*idx[jrow]+3];
1803:       sum5  += v[jrow]*x[10*idx[jrow]+4];
1804:       sum6  += v[jrow]*x[10*idx[jrow]+5];
1805:       sum7  += v[jrow]*x[10*idx[jrow]+6];
1806:       sum8  += v[jrow]*x[10*idx[jrow]+7];
1807:       sum9  += v[jrow]*x[10*idx[jrow]+8];
1808:       sum10 += v[jrow]*x[10*idx[jrow]+9];
1809:       jrow++;
1810:     }
1811:     y[10*i]   += sum1;
1812:     y[10*i+1] += sum2;
1813:     y[10*i+2] += sum3;
1814:     y[10*i+3] += sum4;
1815:     y[10*i+4] += sum5;
1816:     y[10*i+5] += sum6;
1817:     y[10*i+6] += sum7;
1818:     y[10*i+7] += sum8;
1819:     y[10*i+8] += sum9;
1820:     y[10*i+9] += sum10;
1821:   }

1823:   PetscLogFlops(20.0*a->nz);
1824:   VecRestoreArrayRead(xx,&x);
1825:   VecRestoreArray(yy,&y);
1826:   return(0);
1827: }

1831: PetscErrorCode MatMultTranspose_SeqMAIJ_10(Mat A,Vec xx,Vec yy)
1832: {
1833:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1834:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1835:   const PetscScalar *x,*v;
1836:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9,alpha10;
1837:   PetscErrorCode    ierr;
1838:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1839:   PetscInt          n,i;

1842:   VecSet(yy,0.0);
1843:   VecGetArrayRead(xx,&x);
1844:   VecGetArray(yy,&y);

1846:   for (i=0; i<m; i++) {
1847:     idx     = a->j + a->i[i];
1848:     v       = a->a + a->i[i];
1849:     n       = a->i[i+1] - a->i[i];
1850:     alpha1  = x[10*i];
1851:     alpha2  = x[10*i+1];
1852:     alpha3  = x[10*i+2];
1853:     alpha4  = x[10*i+3];
1854:     alpha5  = x[10*i+4];
1855:     alpha6  = x[10*i+5];
1856:     alpha7  = x[10*i+6];
1857:     alpha8  = x[10*i+7];
1858:     alpha9  = x[10*i+8];
1859:     alpha10 = x[10*i+9];
1860:     while (n-->0) {
1861:       y[10*(*idx)]   += alpha1*(*v);
1862:       y[10*(*idx)+1] += alpha2*(*v);
1863:       y[10*(*idx)+2] += alpha3*(*v);
1864:       y[10*(*idx)+3] += alpha4*(*v);
1865:       y[10*(*idx)+4] += alpha5*(*v);
1866:       y[10*(*idx)+5] += alpha6*(*v);
1867:       y[10*(*idx)+6] += alpha7*(*v);
1868:       y[10*(*idx)+7] += alpha8*(*v);
1869:       y[10*(*idx)+8] += alpha9*(*v);
1870:       y[10*(*idx)+9] += alpha10*(*v);
1871:       idx++; v++;
1872:     }
1873:   }
1874:   PetscLogFlops(20.0*a->nz);
1875:   VecRestoreArrayRead(xx,&x);
1876:   VecRestoreArray(yy,&y);
1877:   return(0);
1878: }

1882: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_10(Mat A,Vec xx,Vec yy,Vec zz)
1883: {
1884:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1885:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1886:   const PetscScalar *x,*v;
1887:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9,alpha10;
1888:   PetscErrorCode    ierr;
1889:   const PetscInt    m = b->AIJ->rmap->n,*idx;
1890:   PetscInt          n,i;

1893:   if (yy != zz) {VecCopy(yy,zz);}
1894:   VecGetArrayRead(xx,&x);
1895:   VecGetArray(zz,&y);
1896:   for (i=0; i<m; i++) {
1897:     idx     = a->j + a->i[i];
1898:     v       = a->a + a->i[i];
1899:     n       = a->i[i+1] - a->i[i];
1900:     alpha1  = x[10*i];
1901:     alpha2  = x[10*i+1];
1902:     alpha3  = x[10*i+2];
1903:     alpha4  = x[10*i+3];
1904:     alpha5  = x[10*i+4];
1905:     alpha6  = x[10*i+5];
1906:     alpha7  = x[10*i+6];
1907:     alpha8  = x[10*i+7];
1908:     alpha9  = x[10*i+8];
1909:     alpha10 = x[10*i+9];
1910:     while (n-->0) {
1911:       y[10*(*idx)]   += alpha1*(*v);
1912:       y[10*(*idx)+1] += alpha2*(*v);
1913:       y[10*(*idx)+2] += alpha3*(*v);
1914:       y[10*(*idx)+3] += alpha4*(*v);
1915:       y[10*(*idx)+4] += alpha5*(*v);
1916:       y[10*(*idx)+5] += alpha6*(*v);
1917:       y[10*(*idx)+6] += alpha7*(*v);
1918:       y[10*(*idx)+7] += alpha8*(*v);
1919:       y[10*(*idx)+8] += alpha9*(*v);
1920:       y[10*(*idx)+9] += alpha10*(*v);
1921:       idx++; v++;
1922:     }
1923:   }
1924:   PetscLogFlops(20.0*a->nz);
1925:   VecRestoreArrayRead(xx,&x);
1926:   VecRestoreArray(zz,&y);
1927:   return(0);
1928: }


1931: /*--------------------------------------------------------------------------------------------*/
1934: PetscErrorCode MatMult_SeqMAIJ_11(Mat A,Vec xx,Vec yy)
1935: {
1936:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
1937:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
1938:   const PetscScalar *x,*v;
1939:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9, sum10, sum11;
1940:   PetscErrorCode    ierr;
1941:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
1942:   PetscInt          nonzerorow=0,n,i,jrow,j;

1945:   VecGetArrayRead(xx,&x);
1946:   VecGetArray(yy,&y);
1947:   idx  = a->j;
1948:   v    = a->a;
1949:   ii   = a->i;

1951:   for (i=0; i<m; i++) {
1952:     jrow  = ii[i];
1953:     n     = ii[i+1] - jrow;
1954:     sum1  = 0.0;
1955:     sum2  = 0.0;
1956:     sum3  = 0.0;
1957:     sum4  = 0.0;
1958:     sum5  = 0.0;
1959:     sum6  = 0.0;
1960:     sum7  = 0.0;
1961:     sum8  = 0.0;
1962:     sum9  = 0.0;
1963:     sum10 = 0.0;
1964:     sum11 = 0.0;

1966:     nonzerorow += (n>0);
1967:     for (j=0; j<n; j++) {
1968:       sum1  += v[jrow]*x[11*idx[jrow]];
1969:       sum2  += v[jrow]*x[11*idx[jrow]+1];
1970:       sum3  += v[jrow]*x[11*idx[jrow]+2];
1971:       sum4  += v[jrow]*x[11*idx[jrow]+3];
1972:       sum5  += v[jrow]*x[11*idx[jrow]+4];
1973:       sum6  += v[jrow]*x[11*idx[jrow]+5];
1974:       sum7  += v[jrow]*x[11*idx[jrow]+6];
1975:       sum8  += v[jrow]*x[11*idx[jrow]+7];
1976:       sum9  += v[jrow]*x[11*idx[jrow]+8];
1977:       sum10 += v[jrow]*x[11*idx[jrow]+9];
1978:       sum11 += v[jrow]*x[11*idx[jrow]+10];
1979:       jrow++;
1980:     }
1981:     y[11*i]    = sum1;
1982:     y[11*i+1]  = sum2;
1983:     y[11*i+2]  = sum3;
1984:     y[11*i+3]  = sum4;
1985:     y[11*i+4]  = sum5;
1986:     y[11*i+5]  = sum6;
1987:     y[11*i+6]  = sum7;
1988:     y[11*i+7]  = sum8;
1989:     y[11*i+8]  = sum9;
1990:     y[11*i+9]  = sum10;
1991:     y[11*i+10] = sum11;
1992:   }

1994:   PetscLogFlops(22*a->nz - 11*nonzerorow);
1995:   VecRestoreArrayRead(xx,&x);
1996:   VecRestoreArray(yy,&y);
1997:   return(0);
1998: }

2002: PetscErrorCode MatMultAdd_SeqMAIJ_11(Mat A,Vec xx,Vec yy,Vec zz)
2003: {
2004:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2005:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2006:   const PetscScalar *x,*v;
2007:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8, sum9, sum10, sum11;
2008:   PetscErrorCode    ierr;
2009:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
2010:   PetscInt          n,i,jrow,j;

2013:   if (yy != zz) {VecCopy(yy,zz);}
2014:   VecGetArrayRead(xx,&x);
2015:   VecGetArray(zz,&y);
2016:   idx  = a->j;
2017:   v    = a->a;
2018:   ii   = a->i;

2020:   for (i=0; i<m; i++) {
2021:     jrow  = ii[i];
2022:     n     = ii[i+1] - jrow;
2023:     sum1  = 0.0;
2024:     sum2  = 0.0;
2025:     sum3  = 0.0;
2026:     sum4  = 0.0;
2027:     sum5  = 0.0;
2028:     sum6  = 0.0;
2029:     sum7  = 0.0;
2030:     sum8  = 0.0;
2031:     sum9  = 0.0;
2032:     sum10 = 0.0;
2033:     sum11 = 0.0;
2034:     for (j=0; j<n; j++) {
2035:       sum1  += v[jrow]*x[11*idx[jrow]];
2036:       sum2  += v[jrow]*x[11*idx[jrow]+1];
2037:       sum3  += v[jrow]*x[11*idx[jrow]+2];
2038:       sum4  += v[jrow]*x[11*idx[jrow]+3];
2039:       sum5  += v[jrow]*x[11*idx[jrow]+4];
2040:       sum6  += v[jrow]*x[11*idx[jrow]+5];
2041:       sum7  += v[jrow]*x[11*idx[jrow]+6];
2042:       sum8  += v[jrow]*x[11*idx[jrow]+7];
2043:       sum9  += v[jrow]*x[11*idx[jrow]+8];
2044:       sum10 += v[jrow]*x[11*idx[jrow]+9];
2045:       sum11 += v[jrow]*x[11*idx[jrow]+10];
2046:       jrow++;
2047:     }
2048:     y[11*i]    += sum1;
2049:     y[11*i+1]  += sum2;
2050:     y[11*i+2]  += sum3;
2051:     y[11*i+3]  += sum4;
2052:     y[11*i+4]  += sum5;
2053:     y[11*i+5]  += sum6;
2054:     y[11*i+6]  += sum7;
2055:     y[11*i+7]  += sum8;
2056:     y[11*i+8]  += sum9;
2057:     y[11*i+9]  += sum10;
2058:     y[11*i+10] += sum11;
2059:   }

2061:   PetscLogFlops(22*a->nz);
2062:   VecRestoreArrayRead(xx,&x);
2063:   VecRestoreArray(yy,&y);
2064:   return(0);
2065: }

2069: PetscErrorCode MatMultTranspose_SeqMAIJ_11(Mat A,Vec xx,Vec yy)
2070: {
2071:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2072:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2073:   const PetscScalar *x,*v;
2074:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9,alpha10,alpha11;
2075:   PetscErrorCode    ierr;
2076:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2077:   PetscInt          n,i;

2080:   VecSet(yy,0.0);
2081:   VecGetArrayRead(xx,&x);
2082:   VecGetArray(yy,&y);

2084:   for (i=0; i<m; i++) {
2085:     idx     = a->j + a->i[i];
2086:     v       = a->a + a->i[i];
2087:     n       = a->i[i+1] - a->i[i];
2088:     alpha1  = x[11*i];
2089:     alpha2  = x[11*i+1];
2090:     alpha3  = x[11*i+2];
2091:     alpha4  = x[11*i+3];
2092:     alpha5  = x[11*i+4];
2093:     alpha6  = x[11*i+5];
2094:     alpha7  = x[11*i+6];
2095:     alpha8  = x[11*i+7];
2096:     alpha9  = x[11*i+8];
2097:     alpha10 = x[11*i+9];
2098:     alpha11 = x[11*i+10];
2099:     while (n-->0) {
2100:       y[11*(*idx)]    += alpha1*(*v);
2101:       y[11*(*idx)+1]  += alpha2*(*v);
2102:       y[11*(*idx)+2]  += alpha3*(*v);
2103:       y[11*(*idx)+3]  += alpha4*(*v);
2104:       y[11*(*idx)+4]  += alpha5*(*v);
2105:       y[11*(*idx)+5]  += alpha6*(*v);
2106:       y[11*(*idx)+6]  += alpha7*(*v);
2107:       y[11*(*idx)+7]  += alpha8*(*v);
2108:       y[11*(*idx)+8]  += alpha9*(*v);
2109:       y[11*(*idx)+9]  += alpha10*(*v);
2110:       y[11*(*idx)+10] += alpha11*(*v);
2111:       idx++; v++;
2112:     }
2113:   }
2114:   PetscLogFlops(22*a->nz);
2115:   VecRestoreArrayRead(xx,&x);
2116:   VecRestoreArray(yy,&y);
2117:   return(0);
2118: }

2122: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_11(Mat A,Vec xx,Vec yy,Vec zz)
2123: {
2124:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2125:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2126:   const PetscScalar *x,*v;
2127:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8,alpha9,alpha10,alpha11;
2128:   PetscErrorCode    ierr;
2129:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2130:   PetscInt          n,i;

2133:   if (yy != zz) {VecCopy(yy,zz);}
2134:   VecGetArrayRead(xx,&x);
2135:   VecGetArray(zz,&y);
2136:   for (i=0; i<m; i++) {
2137:     idx     = a->j + a->i[i];
2138:     v       = a->a + a->i[i];
2139:     n       = a->i[i+1] - a->i[i];
2140:     alpha1  = x[11*i];
2141:     alpha2  = x[11*i+1];
2142:     alpha3  = x[11*i+2];
2143:     alpha4  = x[11*i+3];
2144:     alpha5  = x[11*i+4];
2145:     alpha6  = x[11*i+5];
2146:     alpha7  = x[11*i+6];
2147:     alpha8  = x[11*i+7];
2148:     alpha9  = x[11*i+8];
2149:     alpha10 = x[11*i+9];
2150:     alpha11 = x[11*i+10];
2151:     while (n-->0) {
2152:       y[11*(*idx)]    += alpha1*(*v);
2153:       y[11*(*idx)+1]  += alpha2*(*v);
2154:       y[11*(*idx)+2]  += alpha3*(*v);
2155:       y[11*(*idx)+3]  += alpha4*(*v);
2156:       y[11*(*idx)+4]  += alpha5*(*v);
2157:       y[11*(*idx)+5]  += alpha6*(*v);
2158:       y[11*(*idx)+6]  += alpha7*(*v);
2159:       y[11*(*idx)+7]  += alpha8*(*v);
2160:       y[11*(*idx)+8]  += alpha9*(*v);
2161:       y[11*(*idx)+9]  += alpha10*(*v);
2162:       y[11*(*idx)+10] += alpha11*(*v);
2163:       idx++; v++;
2164:     }
2165:   }
2166:   PetscLogFlops(22*a->nz);
2167:   VecRestoreArrayRead(xx,&x);
2168:   VecRestoreArray(zz,&y);
2169:   return(0);
2170: }


2173: /*--------------------------------------------------------------------------------------------*/
2176: PetscErrorCode MatMult_SeqMAIJ_16(Mat A,Vec xx,Vec yy)
2177: {
2178:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2179:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2180:   const PetscScalar *x,*v;
2181:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
2182:   PetscScalar       sum9, sum10, sum11, sum12, sum13, sum14, sum15, sum16;
2183:   PetscErrorCode    ierr;
2184:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
2185:   PetscInt          nonzerorow=0,n,i,jrow,j;

2188:   VecGetArrayRead(xx,&x);
2189:   VecGetArray(yy,&y);
2190:   idx  = a->j;
2191:   v    = a->a;
2192:   ii   = a->i;

2194:   for (i=0; i<m; i++) {
2195:     jrow  = ii[i];
2196:     n     = ii[i+1] - jrow;
2197:     sum1  = 0.0;
2198:     sum2  = 0.0;
2199:     sum3  = 0.0;
2200:     sum4  = 0.0;
2201:     sum5  = 0.0;
2202:     sum6  = 0.0;
2203:     sum7  = 0.0;
2204:     sum8  = 0.0;
2205:     sum9  = 0.0;
2206:     sum10 = 0.0;
2207:     sum11 = 0.0;
2208:     sum12 = 0.0;
2209:     sum13 = 0.0;
2210:     sum14 = 0.0;
2211:     sum15 = 0.0;
2212:     sum16 = 0.0;

2214:     nonzerorow += (n>0);
2215:     for (j=0; j<n; j++) {
2216:       sum1  += v[jrow]*x[16*idx[jrow]];
2217:       sum2  += v[jrow]*x[16*idx[jrow]+1];
2218:       sum3  += v[jrow]*x[16*idx[jrow]+2];
2219:       sum4  += v[jrow]*x[16*idx[jrow]+3];
2220:       sum5  += v[jrow]*x[16*idx[jrow]+4];
2221:       sum6  += v[jrow]*x[16*idx[jrow]+5];
2222:       sum7  += v[jrow]*x[16*idx[jrow]+6];
2223:       sum8  += v[jrow]*x[16*idx[jrow]+7];
2224:       sum9  += v[jrow]*x[16*idx[jrow]+8];
2225:       sum10 += v[jrow]*x[16*idx[jrow]+9];
2226:       sum11 += v[jrow]*x[16*idx[jrow]+10];
2227:       sum12 += v[jrow]*x[16*idx[jrow]+11];
2228:       sum13 += v[jrow]*x[16*idx[jrow]+12];
2229:       sum14 += v[jrow]*x[16*idx[jrow]+13];
2230:       sum15 += v[jrow]*x[16*idx[jrow]+14];
2231:       sum16 += v[jrow]*x[16*idx[jrow]+15];
2232:       jrow++;
2233:     }
2234:     y[16*i]    = sum1;
2235:     y[16*i+1]  = sum2;
2236:     y[16*i+2]  = sum3;
2237:     y[16*i+3]  = sum4;
2238:     y[16*i+4]  = sum5;
2239:     y[16*i+5]  = sum6;
2240:     y[16*i+6]  = sum7;
2241:     y[16*i+7]  = sum8;
2242:     y[16*i+8]  = sum9;
2243:     y[16*i+9]  = sum10;
2244:     y[16*i+10] = sum11;
2245:     y[16*i+11] = sum12;
2246:     y[16*i+12] = sum13;
2247:     y[16*i+13] = sum14;
2248:     y[16*i+14] = sum15;
2249:     y[16*i+15] = sum16;
2250:   }

2252:   PetscLogFlops(32.0*a->nz - 16.0*nonzerorow);
2253:   VecRestoreArrayRead(xx,&x);
2254:   VecRestoreArray(yy,&y);
2255:   return(0);
2256: }

2260: PetscErrorCode MatMultTranspose_SeqMAIJ_16(Mat A,Vec xx,Vec yy)
2261: {
2262:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2263:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2264:   const PetscScalar *x,*v;
2265:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
2266:   PetscScalar       alpha9,alpha10,alpha11,alpha12,alpha13,alpha14,alpha15,alpha16;
2267:   PetscErrorCode    ierr;
2268:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2269:   PetscInt          n,i;

2272:   VecSet(yy,0.0);
2273:   VecGetArrayRead(xx,&x);
2274:   VecGetArray(yy,&y);

2276:   for (i=0; i<m; i++) {
2277:     idx     = a->j + a->i[i];
2278:     v       = a->a + a->i[i];
2279:     n       = a->i[i+1] - a->i[i];
2280:     alpha1  = x[16*i];
2281:     alpha2  = x[16*i+1];
2282:     alpha3  = x[16*i+2];
2283:     alpha4  = x[16*i+3];
2284:     alpha5  = x[16*i+4];
2285:     alpha6  = x[16*i+5];
2286:     alpha7  = x[16*i+6];
2287:     alpha8  = x[16*i+7];
2288:     alpha9  = x[16*i+8];
2289:     alpha10 = x[16*i+9];
2290:     alpha11 = x[16*i+10];
2291:     alpha12 = x[16*i+11];
2292:     alpha13 = x[16*i+12];
2293:     alpha14 = x[16*i+13];
2294:     alpha15 = x[16*i+14];
2295:     alpha16 = x[16*i+15];
2296:     while (n-->0) {
2297:       y[16*(*idx)]    += alpha1*(*v);
2298:       y[16*(*idx)+1]  += alpha2*(*v);
2299:       y[16*(*idx)+2]  += alpha3*(*v);
2300:       y[16*(*idx)+3]  += alpha4*(*v);
2301:       y[16*(*idx)+4]  += alpha5*(*v);
2302:       y[16*(*idx)+5]  += alpha6*(*v);
2303:       y[16*(*idx)+6]  += alpha7*(*v);
2304:       y[16*(*idx)+7]  += alpha8*(*v);
2305:       y[16*(*idx)+8]  += alpha9*(*v);
2306:       y[16*(*idx)+9]  += alpha10*(*v);
2307:       y[16*(*idx)+10] += alpha11*(*v);
2308:       y[16*(*idx)+11] += alpha12*(*v);
2309:       y[16*(*idx)+12] += alpha13*(*v);
2310:       y[16*(*idx)+13] += alpha14*(*v);
2311:       y[16*(*idx)+14] += alpha15*(*v);
2312:       y[16*(*idx)+15] += alpha16*(*v);
2313:       idx++; v++;
2314:     }
2315:   }
2316:   PetscLogFlops(32.0*a->nz);
2317:   VecRestoreArrayRead(xx,&x);
2318:   VecRestoreArray(yy,&y);
2319:   return(0);
2320: }

2324: PetscErrorCode MatMultAdd_SeqMAIJ_16(Mat A,Vec xx,Vec yy,Vec zz)
2325: {
2326:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2327:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2328:   const PetscScalar *x,*v;
2329:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
2330:   PetscScalar       sum9, sum10, sum11, sum12, sum13, sum14, sum15, sum16;
2331:   PetscErrorCode    ierr;
2332:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
2333:   PetscInt          n,i,jrow,j;

2336:   if (yy != zz) {VecCopy(yy,zz);}
2337:   VecGetArrayRead(xx,&x);
2338:   VecGetArray(zz,&y);
2339:   idx  = a->j;
2340:   v    = a->a;
2341:   ii   = a->i;

2343:   for (i=0; i<m; i++) {
2344:     jrow  = ii[i];
2345:     n     = ii[i+1] - jrow;
2346:     sum1  = 0.0;
2347:     sum2  = 0.0;
2348:     sum3  = 0.0;
2349:     sum4  = 0.0;
2350:     sum5  = 0.0;
2351:     sum6  = 0.0;
2352:     sum7  = 0.0;
2353:     sum8  = 0.0;
2354:     sum9  = 0.0;
2355:     sum10 = 0.0;
2356:     sum11 = 0.0;
2357:     sum12 = 0.0;
2358:     sum13 = 0.0;
2359:     sum14 = 0.0;
2360:     sum15 = 0.0;
2361:     sum16 = 0.0;
2362:     for (j=0; j<n; j++) {
2363:       sum1  += v[jrow]*x[16*idx[jrow]];
2364:       sum2  += v[jrow]*x[16*idx[jrow]+1];
2365:       sum3  += v[jrow]*x[16*idx[jrow]+2];
2366:       sum4  += v[jrow]*x[16*idx[jrow]+3];
2367:       sum5  += v[jrow]*x[16*idx[jrow]+4];
2368:       sum6  += v[jrow]*x[16*idx[jrow]+5];
2369:       sum7  += v[jrow]*x[16*idx[jrow]+6];
2370:       sum8  += v[jrow]*x[16*idx[jrow]+7];
2371:       sum9  += v[jrow]*x[16*idx[jrow]+8];
2372:       sum10 += v[jrow]*x[16*idx[jrow]+9];
2373:       sum11 += v[jrow]*x[16*idx[jrow]+10];
2374:       sum12 += v[jrow]*x[16*idx[jrow]+11];
2375:       sum13 += v[jrow]*x[16*idx[jrow]+12];
2376:       sum14 += v[jrow]*x[16*idx[jrow]+13];
2377:       sum15 += v[jrow]*x[16*idx[jrow]+14];
2378:       sum16 += v[jrow]*x[16*idx[jrow]+15];
2379:       jrow++;
2380:     }
2381:     y[16*i]    += sum1;
2382:     y[16*i+1]  += sum2;
2383:     y[16*i+2]  += sum3;
2384:     y[16*i+3]  += sum4;
2385:     y[16*i+4]  += sum5;
2386:     y[16*i+5]  += sum6;
2387:     y[16*i+6]  += sum7;
2388:     y[16*i+7]  += sum8;
2389:     y[16*i+8]  += sum9;
2390:     y[16*i+9]  += sum10;
2391:     y[16*i+10] += sum11;
2392:     y[16*i+11] += sum12;
2393:     y[16*i+12] += sum13;
2394:     y[16*i+13] += sum14;
2395:     y[16*i+14] += sum15;
2396:     y[16*i+15] += sum16;
2397:   }

2399:   PetscLogFlops(32.0*a->nz);
2400:   VecRestoreArrayRead(xx,&x);
2401:   VecRestoreArray(zz,&y);
2402:   return(0);
2403: }

2407: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_16(Mat A,Vec xx,Vec yy,Vec zz)
2408: {
2409:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2410:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2411:   const PetscScalar *x,*v;
2412:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
2413:   PetscScalar       alpha9,alpha10,alpha11,alpha12,alpha13,alpha14,alpha15,alpha16;
2414:   PetscErrorCode    ierr;
2415:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2416:   PetscInt          n,i;

2419:   if (yy != zz) {VecCopy(yy,zz);}
2420:   VecGetArrayRead(xx,&x);
2421:   VecGetArray(zz,&y);
2422:   for (i=0; i<m; i++) {
2423:     idx     = a->j + a->i[i];
2424:     v       = a->a + a->i[i];
2425:     n       = a->i[i+1] - a->i[i];
2426:     alpha1  = x[16*i];
2427:     alpha2  = x[16*i+1];
2428:     alpha3  = x[16*i+2];
2429:     alpha4  = x[16*i+3];
2430:     alpha5  = x[16*i+4];
2431:     alpha6  = x[16*i+5];
2432:     alpha7  = x[16*i+6];
2433:     alpha8  = x[16*i+7];
2434:     alpha9  = x[16*i+8];
2435:     alpha10 = x[16*i+9];
2436:     alpha11 = x[16*i+10];
2437:     alpha12 = x[16*i+11];
2438:     alpha13 = x[16*i+12];
2439:     alpha14 = x[16*i+13];
2440:     alpha15 = x[16*i+14];
2441:     alpha16 = x[16*i+15];
2442:     while (n-->0) {
2443:       y[16*(*idx)]    += alpha1*(*v);
2444:       y[16*(*idx)+1]  += alpha2*(*v);
2445:       y[16*(*idx)+2]  += alpha3*(*v);
2446:       y[16*(*idx)+3]  += alpha4*(*v);
2447:       y[16*(*idx)+4]  += alpha5*(*v);
2448:       y[16*(*idx)+5]  += alpha6*(*v);
2449:       y[16*(*idx)+6]  += alpha7*(*v);
2450:       y[16*(*idx)+7]  += alpha8*(*v);
2451:       y[16*(*idx)+8]  += alpha9*(*v);
2452:       y[16*(*idx)+9]  += alpha10*(*v);
2453:       y[16*(*idx)+10] += alpha11*(*v);
2454:       y[16*(*idx)+11] += alpha12*(*v);
2455:       y[16*(*idx)+12] += alpha13*(*v);
2456:       y[16*(*idx)+13] += alpha14*(*v);
2457:       y[16*(*idx)+14] += alpha15*(*v);
2458:       y[16*(*idx)+15] += alpha16*(*v);
2459:       idx++; v++;
2460:     }
2461:   }
2462:   PetscLogFlops(32.0*a->nz);
2463:   VecRestoreArrayRead(xx,&x);
2464:   VecRestoreArray(zz,&y);
2465:   return(0);
2466: }

2468: /*--------------------------------------------------------------------------------------------*/
2471: PetscErrorCode MatMult_SeqMAIJ_18(Mat A,Vec xx,Vec yy)
2472: {
2473:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2474:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2475:   const PetscScalar *x,*v;
2476:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
2477:   PetscScalar       sum9, sum10, sum11, sum12, sum13, sum14, sum15, sum16, sum17, sum18;
2478:   PetscErrorCode    ierr;
2479:   const PetscInt    m         = b->AIJ->rmap->n,*idx,*ii;
2480:   PetscInt          nonzerorow=0,n,i,jrow,j;

2483:   VecGetArrayRead(xx,&x);
2484:   VecGetArray(yy,&y);
2485:   idx  = a->j;
2486:   v    = a->a;
2487:   ii   = a->i;

2489:   for (i=0; i<m; i++) {
2490:     jrow  = ii[i];
2491:     n     = ii[i+1] - jrow;
2492:     sum1  = 0.0;
2493:     sum2  = 0.0;
2494:     sum3  = 0.0;
2495:     sum4  = 0.0;
2496:     sum5  = 0.0;
2497:     sum6  = 0.0;
2498:     sum7  = 0.0;
2499:     sum8  = 0.0;
2500:     sum9  = 0.0;
2501:     sum10 = 0.0;
2502:     sum11 = 0.0;
2503:     sum12 = 0.0;
2504:     sum13 = 0.0;
2505:     sum14 = 0.0;
2506:     sum15 = 0.0;
2507:     sum16 = 0.0;
2508:     sum17 = 0.0;
2509:     sum18 = 0.0;

2511:     nonzerorow += (n>0);
2512:     for (j=0; j<n; j++) {
2513:       sum1  += v[jrow]*x[18*idx[jrow]];
2514:       sum2  += v[jrow]*x[18*idx[jrow]+1];
2515:       sum3  += v[jrow]*x[18*idx[jrow]+2];
2516:       sum4  += v[jrow]*x[18*idx[jrow]+3];
2517:       sum5  += v[jrow]*x[18*idx[jrow]+4];
2518:       sum6  += v[jrow]*x[18*idx[jrow]+5];
2519:       sum7  += v[jrow]*x[18*idx[jrow]+6];
2520:       sum8  += v[jrow]*x[18*idx[jrow]+7];
2521:       sum9  += v[jrow]*x[18*idx[jrow]+8];
2522:       sum10 += v[jrow]*x[18*idx[jrow]+9];
2523:       sum11 += v[jrow]*x[18*idx[jrow]+10];
2524:       sum12 += v[jrow]*x[18*idx[jrow]+11];
2525:       sum13 += v[jrow]*x[18*idx[jrow]+12];
2526:       sum14 += v[jrow]*x[18*idx[jrow]+13];
2527:       sum15 += v[jrow]*x[18*idx[jrow]+14];
2528:       sum16 += v[jrow]*x[18*idx[jrow]+15];
2529:       sum17 += v[jrow]*x[18*idx[jrow]+16];
2530:       sum18 += v[jrow]*x[18*idx[jrow]+17];
2531:       jrow++;
2532:     }
2533:     y[18*i]    = sum1;
2534:     y[18*i+1]  = sum2;
2535:     y[18*i+2]  = sum3;
2536:     y[18*i+3]  = sum4;
2537:     y[18*i+4]  = sum5;
2538:     y[18*i+5]  = sum6;
2539:     y[18*i+6]  = sum7;
2540:     y[18*i+7]  = sum8;
2541:     y[18*i+8]  = sum9;
2542:     y[18*i+9]  = sum10;
2543:     y[18*i+10] = sum11;
2544:     y[18*i+11] = sum12;
2545:     y[18*i+12] = sum13;
2546:     y[18*i+13] = sum14;
2547:     y[18*i+14] = sum15;
2548:     y[18*i+15] = sum16;
2549:     y[18*i+16] = sum17;
2550:     y[18*i+17] = sum18;
2551:   }

2553:   PetscLogFlops(36.0*a->nz - 18.0*nonzerorow);
2554:   VecRestoreArrayRead(xx,&x);
2555:   VecRestoreArray(yy,&y);
2556:   return(0);
2557: }

2561: PetscErrorCode MatMultTranspose_SeqMAIJ_18(Mat A,Vec xx,Vec yy)
2562: {
2563:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2564:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2565:   const PetscScalar *x,*v;
2566:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
2567:   PetscScalar       alpha9,alpha10,alpha11,alpha12,alpha13,alpha14,alpha15,alpha16,alpha17,alpha18;
2568:   PetscErrorCode    ierr;
2569:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2570:   PetscInt          n,i;

2573:   VecSet(yy,0.0);
2574:   VecGetArrayRead(xx,&x);
2575:   VecGetArray(yy,&y);

2577:   for (i=0; i<m; i++) {
2578:     idx     = a->j + a->i[i];
2579:     v       = a->a + a->i[i];
2580:     n       = a->i[i+1] - a->i[i];
2581:     alpha1  = x[18*i];
2582:     alpha2  = x[18*i+1];
2583:     alpha3  = x[18*i+2];
2584:     alpha4  = x[18*i+3];
2585:     alpha5  = x[18*i+4];
2586:     alpha6  = x[18*i+5];
2587:     alpha7  = x[18*i+6];
2588:     alpha8  = x[18*i+7];
2589:     alpha9  = x[18*i+8];
2590:     alpha10 = x[18*i+9];
2591:     alpha11 = x[18*i+10];
2592:     alpha12 = x[18*i+11];
2593:     alpha13 = x[18*i+12];
2594:     alpha14 = x[18*i+13];
2595:     alpha15 = x[18*i+14];
2596:     alpha16 = x[18*i+15];
2597:     alpha17 = x[18*i+16];
2598:     alpha18 = x[18*i+17];
2599:     while (n-->0) {
2600:       y[18*(*idx)]    += alpha1*(*v);
2601:       y[18*(*idx)+1]  += alpha2*(*v);
2602:       y[18*(*idx)+2]  += alpha3*(*v);
2603:       y[18*(*idx)+3]  += alpha4*(*v);
2604:       y[18*(*idx)+4]  += alpha5*(*v);
2605:       y[18*(*idx)+5]  += alpha6*(*v);
2606:       y[18*(*idx)+6]  += alpha7*(*v);
2607:       y[18*(*idx)+7]  += alpha8*(*v);
2608:       y[18*(*idx)+8]  += alpha9*(*v);
2609:       y[18*(*idx)+9]  += alpha10*(*v);
2610:       y[18*(*idx)+10] += alpha11*(*v);
2611:       y[18*(*idx)+11] += alpha12*(*v);
2612:       y[18*(*idx)+12] += alpha13*(*v);
2613:       y[18*(*idx)+13] += alpha14*(*v);
2614:       y[18*(*idx)+14] += alpha15*(*v);
2615:       y[18*(*idx)+15] += alpha16*(*v);
2616:       y[18*(*idx)+16] += alpha17*(*v);
2617:       y[18*(*idx)+17] += alpha18*(*v);
2618:       idx++; v++;
2619:     }
2620:   }
2621:   PetscLogFlops(36.0*a->nz);
2622:   VecRestoreArrayRead(xx,&x);
2623:   VecRestoreArray(yy,&y);
2624:   return(0);
2625: }

2629: PetscErrorCode MatMultAdd_SeqMAIJ_18(Mat A,Vec xx,Vec yy,Vec zz)
2630: {
2631:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2632:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2633:   const PetscScalar *x,*v;
2634:   PetscScalar       *y,sum1, sum2, sum3, sum4, sum5, sum6, sum7, sum8;
2635:   PetscScalar       sum9, sum10, sum11, sum12, sum13, sum14, sum15, sum16, sum17, sum18;
2636:   PetscErrorCode    ierr;
2637:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
2638:   PetscInt          n,i,jrow,j;

2641:   if (yy != zz) {VecCopy(yy,zz);}
2642:   VecGetArrayRead(xx,&x);
2643:   VecGetArray(zz,&y);
2644:   idx  = a->j;
2645:   v    = a->a;
2646:   ii   = a->i;

2648:   for (i=0; i<m; i++) {
2649:     jrow  = ii[i];
2650:     n     = ii[i+1] - jrow;
2651:     sum1  = 0.0;
2652:     sum2  = 0.0;
2653:     sum3  = 0.0;
2654:     sum4  = 0.0;
2655:     sum5  = 0.0;
2656:     sum6  = 0.0;
2657:     sum7  = 0.0;
2658:     sum8  = 0.0;
2659:     sum9  = 0.0;
2660:     sum10 = 0.0;
2661:     sum11 = 0.0;
2662:     sum12 = 0.0;
2663:     sum13 = 0.0;
2664:     sum14 = 0.0;
2665:     sum15 = 0.0;
2666:     sum16 = 0.0;
2667:     sum17 = 0.0;
2668:     sum18 = 0.0;
2669:     for (j=0; j<n; j++) {
2670:       sum1  += v[jrow]*x[18*idx[jrow]];
2671:       sum2  += v[jrow]*x[18*idx[jrow]+1];
2672:       sum3  += v[jrow]*x[18*idx[jrow]+2];
2673:       sum4  += v[jrow]*x[18*idx[jrow]+3];
2674:       sum5  += v[jrow]*x[18*idx[jrow]+4];
2675:       sum6  += v[jrow]*x[18*idx[jrow]+5];
2676:       sum7  += v[jrow]*x[18*idx[jrow]+6];
2677:       sum8  += v[jrow]*x[18*idx[jrow]+7];
2678:       sum9  += v[jrow]*x[18*idx[jrow]+8];
2679:       sum10 += v[jrow]*x[18*idx[jrow]+9];
2680:       sum11 += v[jrow]*x[18*idx[jrow]+10];
2681:       sum12 += v[jrow]*x[18*idx[jrow]+11];
2682:       sum13 += v[jrow]*x[18*idx[jrow]+12];
2683:       sum14 += v[jrow]*x[18*idx[jrow]+13];
2684:       sum15 += v[jrow]*x[18*idx[jrow]+14];
2685:       sum16 += v[jrow]*x[18*idx[jrow]+15];
2686:       sum17 += v[jrow]*x[18*idx[jrow]+16];
2687:       sum18 += v[jrow]*x[18*idx[jrow]+17];
2688:       jrow++;
2689:     }
2690:     y[18*i]    += sum1;
2691:     y[18*i+1]  += sum2;
2692:     y[18*i+2]  += sum3;
2693:     y[18*i+3]  += sum4;
2694:     y[18*i+4]  += sum5;
2695:     y[18*i+5]  += sum6;
2696:     y[18*i+6]  += sum7;
2697:     y[18*i+7]  += sum8;
2698:     y[18*i+8]  += sum9;
2699:     y[18*i+9]  += sum10;
2700:     y[18*i+10] += sum11;
2701:     y[18*i+11] += sum12;
2702:     y[18*i+12] += sum13;
2703:     y[18*i+13] += sum14;
2704:     y[18*i+14] += sum15;
2705:     y[18*i+15] += sum16;
2706:     y[18*i+16] += sum17;
2707:     y[18*i+17] += sum18;
2708:   }

2710:   PetscLogFlops(36.0*a->nz);
2711:   VecRestoreArrayRead(xx,&x);
2712:   VecRestoreArray(zz,&y);
2713:   return(0);
2714: }

2718: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_18(Mat A,Vec xx,Vec yy,Vec zz)
2719: {
2720:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2721:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2722:   const PetscScalar *x,*v;
2723:   PetscScalar       *y,alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,alpha7,alpha8;
2724:   PetscScalar       alpha9,alpha10,alpha11,alpha12,alpha13,alpha14,alpha15,alpha16,alpha17,alpha18;
2725:   PetscErrorCode    ierr;
2726:   const PetscInt    m = b->AIJ->rmap->n,*idx;
2727:   PetscInt          n,i;

2730:   if (yy != zz) {VecCopy(yy,zz);}
2731:   VecGetArrayRead(xx,&x);
2732:   VecGetArray(zz,&y);
2733:   for (i=0; i<m; i++) {
2734:     idx     = a->j + a->i[i];
2735:     v       = a->a + a->i[i];
2736:     n       = a->i[i+1] - a->i[i];
2737:     alpha1  = x[18*i];
2738:     alpha2  = x[18*i+1];
2739:     alpha3  = x[18*i+2];
2740:     alpha4  = x[18*i+3];
2741:     alpha5  = x[18*i+4];
2742:     alpha6  = x[18*i+5];
2743:     alpha7  = x[18*i+6];
2744:     alpha8  = x[18*i+7];
2745:     alpha9  = x[18*i+8];
2746:     alpha10 = x[18*i+9];
2747:     alpha11 = x[18*i+10];
2748:     alpha12 = x[18*i+11];
2749:     alpha13 = x[18*i+12];
2750:     alpha14 = x[18*i+13];
2751:     alpha15 = x[18*i+14];
2752:     alpha16 = x[18*i+15];
2753:     alpha17 = x[18*i+16];
2754:     alpha18 = x[18*i+17];
2755:     while (n-->0) {
2756:       y[18*(*idx)]    += alpha1*(*v);
2757:       y[18*(*idx)+1]  += alpha2*(*v);
2758:       y[18*(*idx)+2]  += alpha3*(*v);
2759:       y[18*(*idx)+3]  += alpha4*(*v);
2760:       y[18*(*idx)+4]  += alpha5*(*v);
2761:       y[18*(*idx)+5]  += alpha6*(*v);
2762:       y[18*(*idx)+6]  += alpha7*(*v);
2763:       y[18*(*idx)+7]  += alpha8*(*v);
2764:       y[18*(*idx)+8]  += alpha9*(*v);
2765:       y[18*(*idx)+9]  += alpha10*(*v);
2766:       y[18*(*idx)+10] += alpha11*(*v);
2767:       y[18*(*idx)+11] += alpha12*(*v);
2768:       y[18*(*idx)+12] += alpha13*(*v);
2769:       y[18*(*idx)+13] += alpha14*(*v);
2770:       y[18*(*idx)+14] += alpha15*(*v);
2771:       y[18*(*idx)+15] += alpha16*(*v);
2772:       y[18*(*idx)+16] += alpha17*(*v);
2773:       y[18*(*idx)+17] += alpha18*(*v);
2774:       idx++; v++;
2775:     }
2776:   }
2777:   PetscLogFlops(36.0*a->nz);
2778:   VecRestoreArrayRead(xx,&x);
2779:   VecRestoreArray(zz,&y);
2780:   return(0);
2781: }

2785: PetscErrorCode MatMult_SeqMAIJ_N(Mat A,Vec xx,Vec yy)
2786: {
2787:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2788:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2789:   const PetscScalar *x,*v;
2790:   PetscScalar       *y,*sums;
2791:   PetscErrorCode    ierr;
2792:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
2793:   PetscInt          n,i,jrow,j,dof = b->dof,k;

2796:   VecGetArrayRead(xx,&x);
2797:   VecSet(yy,0.0);
2798:   VecGetArray(yy,&y);
2799:   idx  = a->j;
2800:   v    = a->a;
2801:   ii   = a->i;

2803:   for (i=0; i<m; i++) {
2804:     jrow = ii[i];
2805:     n    = ii[i+1] - jrow;
2806:     sums = y + dof*i;
2807:     for (j=0; j<n; j++) {
2808:       for (k=0; k<dof; k++) {
2809:         sums[k] += v[jrow]*x[dof*idx[jrow]+k];
2810:       }
2811:       jrow++;
2812:     }
2813:   }

2815:   PetscLogFlops(2.0*dof*a->nz);
2816:   VecRestoreArrayRead(xx,&x);
2817:   VecRestoreArray(yy,&y);
2818:   return(0);
2819: }

2823: PetscErrorCode MatMultAdd_SeqMAIJ_N(Mat A,Vec xx,Vec yy,Vec zz)
2824: {
2825:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2826:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2827:   const PetscScalar *x,*v;
2828:   PetscScalar       *y,*sums;
2829:   PetscErrorCode    ierr;
2830:   const PetscInt    m = b->AIJ->rmap->n,*idx,*ii;
2831:   PetscInt          n,i,jrow,j,dof = b->dof,k;

2834:   if (yy != zz) {VecCopy(yy,zz);}
2835:   VecGetArrayRead(xx,&x);
2836:   VecGetArray(zz,&y);
2837:   idx  = a->j;
2838:   v    = a->a;
2839:   ii   = a->i;

2841:   for (i=0; i<m; i++) {
2842:     jrow = ii[i];
2843:     n    = ii[i+1] - jrow;
2844:     sums = y + dof*i;
2845:     for (j=0; j<n; j++) {
2846:       for (k=0; k<dof; k++) {
2847:         sums[k] += v[jrow]*x[dof*idx[jrow]+k];
2848:       }
2849:       jrow++;
2850:     }
2851:   }

2853:   PetscLogFlops(2.0*dof*a->nz);
2854:   VecRestoreArrayRead(xx,&x);
2855:   VecRestoreArray(zz,&y);
2856:   return(0);
2857: }

2861: PetscErrorCode MatMultTranspose_SeqMAIJ_N(Mat A,Vec xx,Vec yy)
2862: {
2863:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2864:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2865:   const PetscScalar *x,*v,*alpha;
2866:   PetscScalar       *y;
2867:   PetscErrorCode    ierr;
2868:   const PetscInt    m = b->AIJ->rmap->n,*idx,dof = b->dof;
2869:   PetscInt          n,i,k;

2872:   VecGetArrayRead(xx,&x);
2873:   VecSet(yy,0.0);
2874:   VecGetArray(yy,&y);
2875:   for (i=0; i<m; i++) {
2876:     idx   = a->j + a->i[i];
2877:     v     = a->a + a->i[i];
2878:     n     = a->i[i+1] - a->i[i];
2879:     alpha = x + dof*i;
2880:     while (n-->0) {
2881:       for (k=0; k<dof; k++) {
2882:         y[dof*(*idx)+k] += alpha[k]*(*v);
2883:       }
2884:       idx++; v++;
2885:     }
2886:   }
2887:   PetscLogFlops(2.0*dof*a->nz);
2888:   VecRestoreArrayRead(xx,&x);
2889:   VecRestoreArray(yy,&y);
2890:   return(0);
2891: }

2895: PetscErrorCode MatMultTransposeAdd_SeqMAIJ_N(Mat A,Vec xx,Vec yy,Vec zz)
2896: {
2897:   Mat_SeqMAIJ       *b = (Mat_SeqMAIJ*)A->data;
2898:   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)b->AIJ->data;
2899:   const PetscScalar *x,*v,*alpha;
2900:   PetscScalar       *y;
2901:   PetscErrorCode    ierr;
2902:   const PetscInt    m = b->AIJ->rmap->n,*idx,dof = b->dof;
2903:   PetscInt          n,i,k;

2906:   if (yy != zz) {VecCopy(yy,zz);}
2907:   VecGetArrayRead(xx,&x);
2908:   VecGetArray(zz,&y);
2909:   for (i=0; i<m; i++) {
2910:     idx   = a->j + a->i[i];
2911:     v     = a->a + a->i[i];
2912:     n     = a->i[i+1] - a->i[i];
2913:     alpha = x + dof*i;
2914:     while (n-->0) {
2915:       for (k=0; k<dof; k++) {
2916:         y[dof*(*idx)+k] += alpha[k]*(*v);
2917:       }
2918:       idx++; v++;
2919:     }
2920:   }
2921:   PetscLogFlops(2.0*dof*a->nz);
2922:   VecRestoreArrayRead(xx,&x);
2923:   VecRestoreArray(zz,&y);
2924:   return(0);
2925: }

2927: /*===================================================================================*/
2930: PetscErrorCode MatMult_MPIMAIJ_dof(Mat A,Vec xx,Vec yy)
2931: {
2932:   Mat_MPIMAIJ    *b = (Mat_MPIMAIJ*)A->data;

2936:   /* start the scatter */
2937:   VecScatterBegin(b->ctx,xx,b->w,INSERT_VALUES,SCATTER_FORWARD);
2938:   (*b->AIJ->ops->mult)(b->AIJ,xx,yy);
2939:   VecScatterEnd(b->ctx,xx,b->w,INSERT_VALUES,SCATTER_FORWARD);
2940:   (*b->OAIJ->ops->multadd)(b->OAIJ,b->w,yy,yy);
2941:   return(0);
2942: }

2946: PetscErrorCode MatMultTranspose_MPIMAIJ_dof(Mat A,Vec xx,Vec yy)
2947: {
2948:   Mat_MPIMAIJ    *b = (Mat_MPIMAIJ*)A->data;

2952:   (*b->OAIJ->ops->multtranspose)(b->OAIJ,xx,b->w);
2953:   (*b->AIJ->ops->multtranspose)(b->AIJ,xx,yy);
2954:   VecScatterBegin(b->ctx,b->w,yy,ADD_VALUES,SCATTER_REVERSE);
2955:   VecScatterEnd(b->ctx,b->w,yy,ADD_VALUES,SCATTER_REVERSE);
2956:   return(0);
2957: }

2961: PetscErrorCode MatMultAdd_MPIMAIJ_dof(Mat A,Vec xx,Vec yy,Vec zz)
2962: {
2963:   Mat_MPIMAIJ    *b = (Mat_MPIMAIJ*)A->data;

2967:   /* start the scatter */
2968:   VecScatterBegin(b->ctx,xx,b->w,INSERT_VALUES,SCATTER_FORWARD);
2969:   (*b->AIJ->ops->multadd)(b->AIJ,xx,yy,zz);
2970:   VecScatterEnd(b->ctx,xx,b->w,INSERT_VALUES,SCATTER_FORWARD);
2971:   (*b->OAIJ->ops->multadd)(b->OAIJ,b->w,zz,zz);
2972:   return(0);
2973: }

2977: PetscErrorCode MatMultTransposeAdd_MPIMAIJ_dof(Mat A,Vec xx,Vec yy,Vec zz)
2978: {
2979:   Mat_MPIMAIJ    *b = (Mat_MPIMAIJ*)A->data;

2983:   (*b->OAIJ->ops->multtranspose)(b->OAIJ,xx,b->w);
2984:   VecScatterBegin(b->ctx,b->w,zz,ADD_VALUES,SCATTER_REVERSE);
2985:   (*b->AIJ->ops->multtransposeadd)(b->AIJ,xx,yy,zz);
2986:   VecScatterEnd(b->ctx,b->w,zz,ADD_VALUES,SCATTER_REVERSE);
2987:   return(0);
2988: }

2990: /* ----------------------------------------------------------------*/
2993: PetscErrorCode MatPtAPSymbolic_SeqAIJ_SeqMAIJ(Mat A,Mat PP,PetscReal fill,Mat *C)
2994: {
2995:   PetscErrorCode     ierr;
2996:   PetscFreeSpaceList free_space=NULL,current_space=NULL;
2997:   Mat_SeqMAIJ        *pp       =(Mat_SeqMAIJ*)PP->data;
2998:   Mat                P         =pp->AIJ;
2999:   Mat_SeqAIJ         *a        =(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c;
3000:   PetscInt           *pti,*ptj,*ptJ;
3001:   PetscInt           *ci,*cj,*ptadenserow,*ptasparserow,*denserow,*sparserow,*ptaj;
3002:   const PetscInt     an=A->cmap->N,am=A->rmap->N,pn=P->cmap->N,pm=P->rmap->N,ppdof=pp->dof;
3003:   PetscInt           i,j,k,dof,pshift,ptnzi,arow,anzj,ptanzi,prow,pnzj,cnzi,cn;
3004:   MatScalar          *ca;
3005:   const PetscInt     *pi = p->i,*pj = p->j,*pjj,*ai=a->i,*aj=a->j,*ajj;

3008:   /* Get ij structure of P^T */
3009:   MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);

3011:   cn = pn*ppdof;
3012:   /* Allocate ci array, arrays for fill computation and */
3013:   /* free space for accumulating nonzero column info */
3014:   PetscMalloc1(cn+1,&ci);
3015:   ci[0] = 0;

3017:   /* Work arrays for rows of P^T*A */
3018:   PetscMalloc4(an,&ptadenserow,an,&ptasparserow,cn,&denserow,cn,&sparserow);
3019:   PetscMemzero(ptadenserow,an*sizeof(PetscInt));
3020:   PetscMemzero(denserow,cn*sizeof(PetscInt));

3022:   /* Set initial free space to be nnz(A) scaled by aspect ratio of P. */
3023:   /* This should be reasonable if sparsity of PtAP is similar to that of A. */
3024:   /* Note, aspect ratio of P is the same as the aspect ratio of SeqAIJ inside P */
3025:   PetscFreeSpaceGet(PetscIntMultTruncate(ai[am]/pm,pn),&free_space);
3026:   current_space = free_space;

3028:   /* Determine symbolic info for each row of C: */
3029:   for (i=0; i<pn; i++) {
3030:     ptnzi = pti[i+1] - pti[i];
3031:     ptJ   = ptj + pti[i];
3032:     for (dof=0; dof<ppdof; dof++) {
3033:       ptanzi = 0;
3034:       /* Determine symbolic row of PtA: */
3035:       for (j=0; j<ptnzi; j++) {
3036:         /* Expand ptJ[j] by block size and shift by dof to get the right row of A */
3037:         arow = ptJ[j]*ppdof + dof;
3038:         /* Nonzeros of P^T*A will be in same locations as any element of A in that row */
3039:         anzj = ai[arow+1] - ai[arow];
3040:         ajj  = aj + ai[arow];
3041:         for (k=0; k<anzj; k++) {
3042:           if (!ptadenserow[ajj[k]]) {
3043:             ptadenserow[ajj[k]]    = -1;
3044:             ptasparserow[ptanzi++] = ajj[k];
3045:           }
3046:         }
3047:       }
3048:       /* Using symbolic info for row of PtA, determine symbolic info for row of C: */
3049:       ptaj = ptasparserow;
3050:       cnzi = 0;
3051:       for (j=0; j<ptanzi; j++) {
3052:         /* Get offset within block of P */
3053:         pshift = *ptaj%ppdof;
3054:         /* Get block row of P */
3055:         prow = (*ptaj++)/ppdof; /* integer division */
3056:         /* P has same number of nonzeros per row as the compressed form */
3057:         pnzj = pi[prow+1] - pi[prow];
3058:         pjj  = pj + pi[prow];
3059:         for (k=0;k<pnzj;k++) {
3060:           /* Locations in C are shifted by the offset within the block */
3061:           /* Note: we cannot use PetscLLAdd here because of the additional offset for the write location */
3062:           if (!denserow[pjj[k]*ppdof+pshift]) {
3063:             denserow[pjj[k]*ppdof+pshift] = -1;
3064:             sparserow[cnzi++]             = pjj[k]*ppdof+pshift;
3065:           }
3066:         }
3067:       }

3069:       /* sort sparserow */
3070:       PetscSortInt(cnzi,sparserow);

3072:       /* If free space is not available, make more free space */
3073:       /* Double the amount of total space in the list */
3074:       if (current_space->local_remaining<cnzi) {
3075:         PetscFreeSpaceGet(PetscIntSumTruncate(cnzi,current_space->total_array_size),&current_space);
3076:       }

3078:       /* Copy data into free space, and zero out denserows */
3079:       PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(PetscInt));

3081:       current_space->array           += cnzi;
3082:       current_space->local_used      += cnzi;
3083:       current_space->local_remaining -= cnzi;

3085:       for (j=0; j<ptanzi; j++) ptadenserow[ptasparserow[j]] = 0;
3086:       for (j=0; j<cnzi; j++) denserow[sparserow[j]] = 0;

3088:       /* Aside: Perhaps we should save the pta info for the numerical factorization. */
3089:       /*        For now, we will recompute what is needed. */
3090:       ci[i*ppdof+1+dof] = ci[i*ppdof+dof] + cnzi;
3091:     }
3092:   }
3093:   /* nnz is now stored in ci[ptm], column indices are in the list of free space */
3094:   /* Allocate space for cj, initialize cj, and */
3095:   /* destroy list of free space and other temporary array(s) */
3096:   PetscMalloc1(ci[cn]+1,&cj);
3097:   PetscFreeSpaceContiguous(&free_space,cj);
3098:   PetscFree4(ptadenserow,ptasparserow,denserow,sparserow);

3100:   /* Allocate space for ca */
3101:   PetscCalloc1(ci[cn]+1,&ca);

3103:   /* put together the new matrix */
3104:   MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),cn,cn,ci,cj,ca,C);
3105:   MatSetBlockSize(*C,pp->dof);

3107:   /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
3108:   /* Since these are PETSc arrays, change flags to free them as necessary. */
3109:   c          = (Mat_SeqAIJ*)((*C)->data);
3110:   c->free_a  = PETSC_TRUE;
3111:   c->free_ij = PETSC_TRUE;
3112:   c->nonew   = 0;

3114:   (*C)->ops->ptapnumeric = MatPtAPNumeric_SeqAIJ_SeqMAIJ;

3116:   /* Clean up. */
3117:   MatRestoreSymbolicTranspose_SeqAIJ(P,&pti,&ptj);
3118:   return(0);
3119: }

3123: PetscErrorCode MatPtAPNumeric_SeqAIJ_SeqMAIJ(Mat A,Mat PP,Mat C)
3124: {
3125:   /* This routine requires testing -- first draft only */
3126:   PetscErrorCode  ierr;
3127:   Mat_SeqMAIJ     *pp=(Mat_SeqMAIJ*)PP->data;
3128:   Mat             P  =pp->AIJ;
3129:   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3130:   Mat_SeqAIJ      *p = (Mat_SeqAIJ*) P->data;
3131:   Mat_SeqAIJ      *c = (Mat_SeqAIJ*) C->data;
3132:   const PetscInt  *ai=a->i,*aj=a->j,*pi=p->i,*pj=p->j,*pJ,*pjj;
3133:   const PetscInt  *ci=c->i,*cj=c->j,*cjj;
3134:   const PetscInt  am =A->rmap->N,cn=C->cmap->N,cm=C->rmap->N,ppdof=pp->dof;
3135:   PetscInt        i,j,k,pshift,poffset,anzi,pnzi,apnzj,nextap,pnzj,prow,crow,*apj,*apjdense;
3136:   const MatScalar *aa=a->a,*pa=p->a,*pA,*paj;
3137:   MatScalar       *ca=c->a,*caj,*apa;

3140:   /* Allocate temporary array for storage of one row of A*P */
3141:   PetscCalloc3(cn,&apa,cn,&apj,cn,&apjdense);

3143:   /* Clear old values in C */
3144:   PetscMemzero(ca,ci[cm]*sizeof(MatScalar));

3146:   for (i=0; i<am; i++) {
3147:     /* Form sparse row of A*P */
3148:     anzi  = ai[i+1] - ai[i];
3149:     apnzj = 0;
3150:     for (j=0; j<anzi; j++) {
3151:       /* Get offset within block of P */
3152:       pshift = *aj%ppdof;
3153:       /* Get block row of P */
3154:       prow = *aj++/ppdof;   /* integer division */
3155:       pnzj = pi[prow+1] - pi[prow];
3156:       pjj  = pj + pi[prow];
3157:       paj  = pa + pi[prow];
3158:       for (k=0; k<pnzj; k++) {
3159:         poffset = pjj[k]*ppdof+pshift;
3160:         if (!apjdense[poffset]) {
3161:           apjdense[poffset] = -1;
3162:           apj[apnzj++]      = poffset;
3163:         }
3164:         apa[poffset] += (*aa)*paj[k];
3165:       }
3166:       PetscLogFlops(2.0*pnzj);
3167:       aa++;
3168:     }

3170:     /* Sort the j index array for quick sparse axpy. */
3171:     /* Note: a array does not need sorting as it is in dense storage locations. */
3172:     PetscSortInt(apnzj,apj);

3174:     /* Compute P^T*A*P using outer product (P^T)[:,j]*(A*P)[j,:]. */
3175:     prow    = i/ppdof; /* integer division */
3176:     pshift  = i%ppdof;
3177:     poffset = pi[prow];
3178:     pnzi    = pi[prow+1] - poffset;
3179:     /* Reset pJ and pA so we can traverse the same row of P 'dof' times. */
3180:     pJ = pj+poffset;
3181:     pA = pa+poffset;
3182:     for (j=0; j<pnzi; j++) {
3183:       crow = (*pJ)*ppdof+pshift;
3184:       cjj  = cj + ci[crow];
3185:       caj  = ca + ci[crow];
3186:       pJ++;
3187:       /* Perform sparse axpy operation.  Note cjj includes apj. */
3188:       for (k=0,nextap=0; nextap<apnzj; k++) {
3189:         if (cjj[k] == apj[nextap]) caj[k] += (*pA)*apa[apj[nextap++]];
3190:       }
3191:       PetscLogFlops(2.0*apnzj);
3192:       pA++;
3193:     }

3195:     /* Zero the current row info for A*P */
3196:     for (j=0; j<apnzj; j++) {
3197:       apa[apj[j]]      = 0.;
3198:       apjdense[apj[j]] = 0;
3199:     }
3200:   }

3202:   /* Assemble the final matrix and clean up */
3203:   MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
3204:   MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
3205:   PetscFree3(apa,apj,apjdense);
3206:   return(0);
3207: }

3211: PETSC_INTERN PetscErrorCode MatPtAP_SeqAIJ_SeqMAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
3212: {

3216:   if (scall == MAT_INITIAL_MATRIX) {
3217:     PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);
3218:     MatPtAPSymbolic_SeqAIJ_SeqMAIJ(A,P,fill,C);
3219:     PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);
3220:   }
3221:   PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);
3222:   MatPtAPNumeric_SeqAIJ_SeqMAIJ(A,P,*C);
3223:   PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);
3224:   return(0);
3225: }

3229: PetscErrorCode MatPtAPSymbolic_MPIAIJ_MPIMAIJ(Mat A,Mat PP,PetscReal fill,Mat *C)
3230: {

3234:   /* MatPtAPSymbolic_MPIAIJ_MPIMAIJ() is not implemented yet. Convert PP to mpiaij format */
3235:   MatConvert(PP,MATMPIAIJ,MAT_INPLACE_MATRIX,&PP);
3236:   ierr =(*PP->ops->ptapsymbolic)(A,PP,fill,C);
3237:   return(0);
3238: }

3242: PetscErrorCode MatPtAPNumeric_MPIAIJ_MPIMAIJ(Mat A,Mat PP,Mat C)
3243: {
3245:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatPtAPNumeric is not implemented for MPIMAIJ matrix yet");
3246:   return(0);
3247: }

3251: PETSC_INTERN PetscErrorCode MatPtAP_MPIAIJ_MPIMAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
3252: {

3256:   if (scall == MAT_INITIAL_MATRIX) {
3257:     PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);
3258:     MatPtAPSymbolic_MPIAIJ_MPIMAIJ(A,P,fill,C);
3259:     PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);
3260:   }
3261:   PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);
3262:   ((*C)->ops->ptapnumeric)(A,P,*C);
3263:   PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);
3264:   return(0);
3265: }

3269: PETSC_INTERN PetscErrorCode MatConvert_SeqMAIJ_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
3270: {
3271:   Mat_SeqMAIJ    *b   = (Mat_SeqMAIJ*)A->data;
3272:   Mat            a    = b->AIJ,B;
3273:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)a->data;
3275:   PetscInt       m,n,i,ncols,*ilen,nmax = 0,*icols,j,k,ii,dof = b->dof;
3276:   PetscInt       *cols;
3277:   PetscScalar    *vals;

3280:   MatGetSize(a,&m,&n);
3281:   PetscMalloc1(dof*m,&ilen);
3282:   for (i=0; i<m; i++) {
3283:     nmax = PetscMax(nmax,aij->ilen[i]);
3284:     for (j=0; j<dof; j++) ilen[dof*i+j] = aij->ilen[i];
3285:   }
3286:   MatCreateSeqAIJ(PETSC_COMM_SELF,dof*m,dof*n,0,ilen,&B);
3287:   PetscFree(ilen);
3288:   PetscMalloc1(nmax,&icols);
3289:   ii   = 0;
3290:   for (i=0; i<m; i++) {
3291:     MatGetRow_SeqAIJ(a,i,&ncols,&cols,&vals);
3292:     for (j=0; j<dof; j++) {
3293:       for (k=0; k<ncols; k++) icols[k] = dof*cols[k]+j;
3294:       MatSetValues_SeqAIJ(B,1,&ii,ncols,icols,vals,INSERT_VALUES);
3295:       ii++;
3296:     }
3297:     MatRestoreRow_SeqAIJ(a,i,&ncols,&cols,&vals);
3298:   }
3299:   PetscFree(icols);
3300:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3301:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);

3303:   if (reuse == MAT_INPLACE_MATRIX) {
3304:     MatHeaderReplace(A,&B);
3305:   } else {
3306:     *newmat = B;
3307:   }
3308:   return(0);
3309: }

3311: #include <../src/mat/impls/aij/mpi/mpiaij.h>

3315: PETSC_INTERN PetscErrorCode MatConvert_MPIMAIJ_MPIAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
3316: {
3317:   Mat_MPIMAIJ    *maij   = (Mat_MPIMAIJ*)A->data;
3318:   Mat            MatAIJ  = ((Mat_SeqMAIJ*)maij->AIJ->data)->AIJ,B;
3319:   Mat            MatOAIJ = ((Mat_SeqMAIJ*)maij->OAIJ->data)->AIJ;
3320:   Mat_SeqAIJ     *AIJ    = (Mat_SeqAIJ*) MatAIJ->data;
3321:   Mat_SeqAIJ     *OAIJ   =(Mat_SeqAIJ*) MatOAIJ->data;
3322:   Mat_MPIAIJ     *mpiaij = (Mat_MPIAIJ*) maij->A->data;
3323:   PetscInt       dof     = maij->dof,i,j,*dnz = NULL,*onz = NULL,nmax = 0,onmax = 0;
3324:   PetscInt       *oicols = NULL,*icols = NULL,ncols,*cols = NULL,oncols,*ocols = NULL;
3325:   PetscInt       rstart,cstart,*garray,ii,k;
3327:   PetscScalar    *vals,*ovals;

3330:   PetscMalloc2(A->rmap->n,&dnz,A->rmap->n,&onz);
3331:   for (i=0; i<A->rmap->n/dof; i++) {
3332:     nmax  = PetscMax(nmax,AIJ->ilen[i]);
3333:     onmax = PetscMax(onmax,OAIJ->ilen[i]);
3334:     for (j=0; j<dof; j++) {
3335:       dnz[dof*i+j] = AIJ->ilen[i];
3336:       onz[dof*i+j] = OAIJ->ilen[i];
3337:     }
3338:   }
3339:   MatCreateAIJ(PetscObjectComm((PetscObject)A),A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,0,dnz,0,onz,&B);
3340:   MatSetBlockSize(B,dof);
3341:   PetscFree2(dnz,onz);

3343:   PetscMalloc2(nmax,&icols,onmax,&oicols);
3344:   rstart = dof*maij->A->rmap->rstart;
3345:   cstart = dof*maij->A->cmap->rstart;
3346:   garray = mpiaij->garray;

3348:   ii = rstart;
3349:   for (i=0; i<A->rmap->n/dof; i++) {
3350:     MatGetRow_SeqAIJ(MatAIJ,i,&ncols,&cols,&vals);
3351:     MatGetRow_SeqAIJ(MatOAIJ,i,&oncols,&ocols,&ovals);
3352:     for (j=0; j<dof; j++) {
3353:       for (k=0; k<ncols; k++) {
3354:         icols[k] = cstart + dof*cols[k]+j;
3355:       }
3356:       for (k=0; k<oncols; k++) {
3357:         oicols[k] = dof*garray[ocols[k]]+j;
3358:       }
3359:       MatSetValues_MPIAIJ(B,1,&ii,ncols,icols,vals,INSERT_VALUES);
3360:       MatSetValues_MPIAIJ(B,1,&ii,oncols,oicols,ovals,INSERT_VALUES);
3361:       ii++;
3362:     }
3363:     MatRestoreRow_SeqAIJ(MatAIJ,i,&ncols,&cols,&vals);
3364:     MatRestoreRow_SeqAIJ(MatOAIJ,i,&oncols,&ocols,&ovals);
3365:   }
3366:   PetscFree2(icols,oicols);

3368:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
3369:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);

3371:   if (reuse == MAT_INPLACE_MATRIX) {
3372:     PetscInt refct = ((PetscObject)A)->refct; /* save ((PetscObject)A)->refct */
3373:     ((PetscObject)A)->refct = 1;

3375:     MatHeaderReplace(A,&B);

3377:     ((PetscObject)A)->refct = refct; /* restore ((PetscObject)A)->refct */
3378:   } else {
3379:     *newmat = B;
3380:   }
3381:   return(0);
3382: }

3386: PetscErrorCode  MatGetSubMatrix_MAIJ(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat *newmat)
3387: {
3389:   Mat            A;

3392:   MatConvert(mat,MATAIJ,MAT_INITIAL_MATRIX,&A);
3393:   MatGetSubMatrix(A,isrow,iscol,cll,newmat);
3394:   MatDestroy(&A);
3395:   return(0);
3396: }

3398: /* ---------------------------------------------------------------------------------- */
3401: /*@C
3402:   MatCreateMAIJ - Creates a matrix type providing restriction and interpolation
3403:   operations for multicomponent problems.  It interpolates each component the same
3404:   way independently.  The matrix type is based on MATSEQAIJ for sequential matrices,
3405:   and MATMPIAIJ for distributed matrices.

3407:   Collective

3409:   Input Parameters:
3410: + A - the AIJ matrix describing the action on blocks
3411: - dof - the block size (number of components per node)

3413:   Output Parameter:
3414: . maij - the new MAIJ matrix

3416:   Operations provided:
3417: + MatMult
3418: . MatMultTranspose
3419: . MatMultAdd
3420: . MatMultTransposeAdd
3421: - MatView

3423:   Level: advanced

3425: .seealso: MatMAIJGetAIJ(), MatMAIJRedimension(), MATMAIJ
3426: @*/
3427: PetscErrorCode  MatCreateMAIJ(Mat A,PetscInt dof,Mat *maij)
3428: {
3430:   PetscMPIInt    size;
3431:   PetscInt       n;
3432:   Mat            B;

3435:   PetscObjectReference((PetscObject)A);

3437:   if (dof == 1) *maij = A;
3438:   else {
3439:     MatCreate(PetscObjectComm((PetscObject)A),&B);
3440:     MatSetSizes(B,dof*A->rmap->n,dof*A->cmap->n,dof*A->rmap->N,dof*A->cmap->N);
3441:     PetscLayoutSetBlockSize(B->rmap,dof);
3442:     PetscLayoutSetBlockSize(B->cmap,dof);
3443:     PetscLayoutSetUp(B->rmap);
3444:     PetscLayoutSetUp(B->cmap);

3446:     B->assembled = PETSC_TRUE;

3448:     MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);
3449:     if (size == 1) {
3450:       Mat_SeqMAIJ *b;

3452:       MatSetType(B,MATSEQMAIJ);

3454:       B->ops->setup   = NULL;
3455:       B->ops->destroy = MatDestroy_SeqMAIJ;
3456:       B->ops->view    = MatView_SeqMAIJ;
3457:       b               = (Mat_SeqMAIJ*)B->data;
3458:       b->dof          = dof;
3459:       b->AIJ          = A;

3461:       if (dof == 2) {
3462:         B->ops->mult             = MatMult_SeqMAIJ_2;
3463:         B->ops->multadd          = MatMultAdd_SeqMAIJ_2;
3464:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_2;
3465:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_2;
3466:       } else if (dof == 3) {
3467:         B->ops->mult             = MatMult_SeqMAIJ_3;
3468:         B->ops->multadd          = MatMultAdd_SeqMAIJ_3;
3469:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_3;
3470:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_3;
3471:       } else if (dof == 4) {
3472:         B->ops->mult             = MatMult_SeqMAIJ_4;
3473:         B->ops->multadd          = MatMultAdd_SeqMAIJ_4;
3474:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_4;
3475:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_4;
3476:       } else if (dof == 5) {
3477:         B->ops->mult             = MatMult_SeqMAIJ_5;
3478:         B->ops->multadd          = MatMultAdd_SeqMAIJ_5;
3479:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_5;
3480:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_5;
3481:       } else if (dof == 6) {
3482:         B->ops->mult             = MatMult_SeqMAIJ_6;
3483:         B->ops->multadd          = MatMultAdd_SeqMAIJ_6;
3484:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_6;
3485:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_6;
3486:       } else if (dof == 7) {
3487:         B->ops->mult             = MatMult_SeqMAIJ_7;
3488:         B->ops->multadd          = MatMultAdd_SeqMAIJ_7;
3489:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_7;
3490:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_7;
3491:       } else if (dof == 8) {
3492:         B->ops->mult             = MatMult_SeqMAIJ_8;
3493:         B->ops->multadd          = MatMultAdd_SeqMAIJ_8;
3494:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_8;
3495:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_8;
3496:       } else if (dof == 9) {
3497:         B->ops->mult             = MatMult_SeqMAIJ_9;
3498:         B->ops->multadd          = MatMultAdd_SeqMAIJ_9;
3499:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_9;
3500:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_9;
3501:       } else if (dof == 10) {
3502:         B->ops->mult             = MatMult_SeqMAIJ_10;
3503:         B->ops->multadd          = MatMultAdd_SeqMAIJ_10;
3504:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_10;
3505:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_10;
3506:       } else if (dof == 11) {
3507:         B->ops->mult             = MatMult_SeqMAIJ_11;
3508:         B->ops->multadd          = MatMultAdd_SeqMAIJ_11;
3509:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_11;
3510:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_11;
3511:       } else if (dof == 16) {
3512:         B->ops->mult             = MatMult_SeqMAIJ_16;
3513:         B->ops->multadd          = MatMultAdd_SeqMAIJ_16;
3514:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_16;
3515:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_16;
3516:       } else if (dof == 18) {
3517:         B->ops->mult             = MatMult_SeqMAIJ_18;
3518:         B->ops->multadd          = MatMultAdd_SeqMAIJ_18;
3519:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_18;
3520:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_18;
3521:       } else {
3522:         B->ops->mult             = MatMult_SeqMAIJ_N;
3523:         B->ops->multadd          = MatMultAdd_SeqMAIJ_N;
3524:         B->ops->multtranspose    = MatMultTranspose_SeqMAIJ_N;
3525:         B->ops->multtransposeadd = MatMultTransposeAdd_SeqMAIJ_N;
3526:       }
3527:       PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqmaij_seqaij_C",MatConvert_SeqMAIJ_SeqAIJ);
3528:       PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_seqmaij_C",MatPtAP_SeqAIJ_SeqMAIJ);
3529:     } else {
3530:       Mat_MPIAIJ  *mpiaij = (Mat_MPIAIJ*)A->data;
3531:       Mat_MPIMAIJ *b;
3532:       IS          from,to;
3533:       Vec         gvec;

3535:       MatSetType(B,MATMPIMAIJ);

3537:       B->ops->setup   = NULL;
3538:       B->ops->destroy = MatDestroy_MPIMAIJ;
3539:       B->ops->view    = MatView_MPIMAIJ;

3541:       b      = (Mat_MPIMAIJ*)B->data;
3542:       b->dof = dof;
3543:       b->A   = A;

3545:       MatCreateMAIJ(mpiaij->A,dof,&b->AIJ);
3546:       MatCreateMAIJ(mpiaij->B,dof,&b->OAIJ);

3548:       VecGetSize(mpiaij->lvec,&n);
3549:       VecCreate(PETSC_COMM_SELF,&b->w);
3550:       VecSetSizes(b->w,n*dof,n*dof);
3551:       VecSetBlockSize(b->w,dof);
3552:       VecSetType(b->w,VECSEQ);

3554:       /* create two temporary Index sets for build scatter gather */
3555:       ISCreateBlock(PetscObjectComm((PetscObject)A),dof,n,mpiaij->garray,PETSC_COPY_VALUES,&from);
3556:       ISCreateStride(PETSC_COMM_SELF,n*dof,0,1,&to);

3558:       /* create temporary global vector to generate scatter context */
3559:       VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),dof,dof*A->cmap->n,dof*A->cmap->N,NULL,&gvec);

3561:       /* generate the scatter context */
3562:       VecScatterCreate(gvec,from,b->w,to,&b->ctx);

3564:       ISDestroy(&from);
3565:       ISDestroy(&to);
3566:       VecDestroy(&gvec);

3568:       B->ops->mult             = MatMult_MPIMAIJ_dof;
3569:       B->ops->multtranspose    = MatMultTranspose_MPIMAIJ_dof;
3570:       B->ops->multadd          = MatMultAdd_MPIMAIJ_dof;
3571:       B->ops->multtransposeadd = MatMultTransposeAdd_MPIMAIJ_dof;

3573:       PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpimaij_mpiaij_C",MatConvert_MPIMAIJ_MPIAIJ);
3574:       PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_mpimaij_C",MatPtAP_MPIAIJ_MPIMAIJ);
3575:     }
3576:     B->ops->getsubmatrix = MatGetSubMatrix_MAIJ;
3577:     MatSetUp(B);
3578:     *maij = B;
3579:     MatViewFromOptions(B,NULL,"-mat_view");
3580:   }
3581:   return(0);
3582: }