/[escript]/trunk/paso/src/SystemMatrix_MatrixVector.c
ViewVC logotype

Diff of /trunk/paso/src/SystemMatrix_MatrixVector.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/paso/src/SystemMatrix_MatrixVector.c revision 633 by dhawcroft, Thu Mar 23 05:37:00 2006 UTC temp_trunk_copy/paso/src/SystemMatrix_MatrixVector.c revision 1384 by phornby, Fri Jan 11 02:29:38 2008 UTC
# Line 1  Line 1 
 /* $Id$ */  
1    
2    /* $Id$ */
3    
4  /*  /*******************************************************
5  ********************************************************************************   *
6  *               Copyright   2006 by ACcESS MNRF                                *   *           Copyright 2003-2007 by ACceSS MNRF
7  *                                                                              *   *       Copyright 2007 by University of Queensland
8  *                 http://www.access.edu.au                                     *   *
9  *           Primary Business: Queensland, Australia                            *   *                http://esscc.uq.edu.au
10  *     Licensed under the Open Software License version 3.0             *   *        Primary Business: Queensland, Australia
11  *        http://www.opensource.org/licenses/osl-3.0.php                        *   *  Licensed under the Open Software License version 3.0
12  ********************************************************************************   *     http://www.opensource.org/licenses/osl-3.0.php
13  */   *
14     *******************************************************/
15    
16  /**************************************************************/  /**************************************************************/
17    
# Line 34  Line 35 
35  /* barrier synconization is performed to make sure that the input vector available */  /* barrier synconization is performed to make sure that the input vector available */
36    
37  void  Paso_SystemMatrix_MatrixVector(double alpha,  void  Paso_SystemMatrix_MatrixVector(double alpha,
38      Paso_SystemMatrix* A,                                       Paso_SystemMatrix* A,
39      double* in,                                       double* in,
40      double beta,                                       double beta,
41      double* out) {                                       double* out) {
42    
43      double *snd_buffer=NULL, *rcv_buffer=NULL;
44      dim_t N;
45      Paso_MPIInfo *mpi_info=A->mpi_info;
46    
47    if (A->type & MATRIX_FORMAT_CSC) {    if (A->type & MATRIX_FORMAT_CSC) {
48       if (A->type & MATRIX_FORMAT_OFFSET1) {       if ( mpi_info->size>1) {
49         Paso_SystemMatrix_MatrixVector_CSC_OFFSET1(alpha,A,in,beta,out);             Paso_setError(SYSTEM_ERROR,"Paso_SystemMatrix_MatrixVector: CSC is not supported by MPI.");
50               return;
51       } else {       } else {
52         Paso_SystemMatrix_MatrixVector_CSC_OFFSET0(alpha,A,in,beta,out);         if (A->type & MATRIX_FORMAT_OFFSET1) {
53             Paso_SparseMatrix_MatrixVector_CSC_OFFSET1(alpha,A->mainBlock,in,beta,out);
54           } else {
55             Paso_SparseMatrix_MatrixVector_CSC_OFFSET0(alpha,A->mainBlock,in,beta,out);
56           }
57       }       }
58      } else if (A->type & MATRIX_FORMAT_TRILINOS_CRS) {
59               Paso_setError(SYSTEM_ERROR,"Paso_SystemMatrix_MatrixVector: TRILINOS is not supported with MPI.");
60               return;
61    } else {    } else {
62       if (A->type & MATRIX_FORMAT_OFFSET1) {       if (A->type & MATRIX_FORMAT_OFFSET1) {
63         Paso_SystemMatrix_MatrixVector_CSR_OFFSET1(alpha,A,in,beta,out);             if ( mpi_info->size>1) {
64                  Paso_setError(SYSTEM_ERROR,"Paso_SystemMatrix_MatrixVector: CSR with index 1 is not supported by MPI.");
65                  return;
66               } else {
67                  Paso_SparseMatrix_MatrixVector_CSR_OFFSET1(alpha,A->mainBlock,in,beta,out);
68               }
69       } else {       } else {
70         Paso_SystemMatrix_MatrixVector_CSR_OFFSET0(alpha,A,in,beta,out);           Paso_SystemMatrix_allocBuffer(A);
71             if (Paso_noError()) {
72                Paso_SystemMatrix_MatrixVector_CSR_OFFSET0(alpha,A,in,beta,out);
73             }
74             Paso_SystemMatrix_freeBuffer(A);
75       }       }
76    }    }
   return;  
 }  
   
 void  Paso_SystemMatrix_MatrixVector_CSC_OFFSET0(double alpha,  
     Paso_SystemMatrix* A,  
     double* in,  
     double beta,  
     double* out) {  
   
   register index_t ir,icol,iptr,icb,irb,irow,ic;  
   register double reg,reg1,reg2,reg3;  
   #pragma omp barrier  
   
   if (ABS(beta)>0.) {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] *= beta;  
   } else {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] = 0;  
   }  
         
   /*  do the operation: */  
   if (ABS(alpha)>0) {  
     if (A ->col_block_size==1 && A->row_block_size ==1) {  
         /* TODO: parallelize (good luck!) */  
         #pragma omp single  
     for (icol=0;icol< A->pattern->n_ptr;++icol) {  
       for (iptr=A->pattern->ptr[icol];iptr<A->pattern->ptr[icol+1]; ++iptr) {  
         out[A->pattern->index[iptr]]+= alpha * A->val[iptr] * in[icol];  
       }  
     }  
     } else if (A ->col_block_size==2 && A->row_block_size ==2) {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic];iptr<A->pattern->ptr[ic+1]; iptr++) {  
            ic=2*(A->pattern->index[iptr]);  
            out[  2*ir] += alpha * ( A->val[iptr*4  ]*in[ic] + A->val[iptr*4+2]*in[1+ic] );  
            out[1+2*ir] += alpha * ( A->val[iptr*4+1]*in[ic] + A->val[iptr*4+3]*in[1+ic] );  
       }  
     }  
     } else if (A ->col_block_size==3 && A->row_block_size ==3) {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic];iptr<A->pattern->ptr[ic+1]; iptr++) {  
           ir=3*(A->pattern->index[iptr]);  
               out[  3*ir] += alpha * ( A->val[iptr*9  ]*in[ic] + A->val[iptr*9+3]*in[1+ic] + A->val[iptr*9+6]*in[2+ic] );  
           out[1+3*ir] += alpha * ( A->val[iptr*9+1]*in[ic] + A->val[iptr*9+4]*in[1+ic] + A->val[iptr*9+7]*in[2+ic] );  
           out[2+3*ir] += alpha * ( A->val[iptr*9+2]*in[ic] + A->val[iptr*9+5]*in[1+ic] + A->val[iptr*9+8]*in[2+ic] );  
       }  
     }  
     } else {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic];iptr<A->pattern->ptr[ic+1]; iptr++) {  
         for (irb=0;irb< A->row_block_size;irb++) {  
           irow=irb+A->row_block_size*(A->pattern->index[iptr]);  
           for (icb=0;icb< A->col_block_size;icb++) {  
         icol=icb+A->col_block_size*ic;  
         out[irow] += alpha * A->val[iptr*A->block_size+irb+A->row_block_size*icb] * in[icol];  
           }  
         }  
       }  
     }  
     }  
   }  
   return;  
 }  
   
 void  Paso_SystemMatrix_MatrixVector_CSC_OFFSET1(double alpha,  
     Paso_SystemMatrix* A,  
     double* in,  
     double beta,  
     double* out) {  
   
   register index_t ir,icol,iptr,icb,irb,irow,ic;  
   register double reg,reg1,reg2,reg3;  
   #pragma omp barrier  
   
   if (ABS(beta)>0.) {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] *= beta;  
   } else {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] = 0;  
   }  
         
   /*  do the operation: */  
   if (ABS(alpha)>0) {  
     if (A ->col_block_size==1 && A->row_block_size ==1) {  
         /* TODO: parallelize (good luck!) */  
         #pragma omp single  
     for (icol=0;icol< A->pattern->n_ptr;++icol) {  
       for (iptr=A->pattern->ptr[icol]-1;iptr<A->pattern->ptr[icol+1]-1; ++iptr) {  
         out[A->pattern->index[iptr]-1]+= alpha * A->val[iptr] * in[icol];  
       }  
     }  
     } else if (A ->col_block_size==2 && A->row_block_size ==2) {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic]-1;iptr<A->pattern->ptr[ic+1]-1; iptr++) {  
            ic=2*(A->pattern->index[iptr]-1);  
            out[  2*ir] += alpha * ( A->val[iptr*4  ]*in[ic] + A->val[iptr*4+2]*in[1+ic] );  
            out[1+2*ir] += alpha * ( A->val[iptr*4+1]*in[ic] + A->val[iptr*4+3]*in[1+ic] );  
       }  
     }  
     } else if (A ->col_block_size==3 && A->row_block_size ==3) {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic]-1;iptr<A->pattern->ptr[ic+1]-1; iptr++) {  
           ir=3*(A->pattern->index[iptr]-1);  
               out[  3*ir] += alpha * ( A->val[iptr*9  ]*in[ic] + A->val[iptr*9+3]*in[1+ic] + A->val[iptr*9+6]*in[2+ic] );  
           out[1+3*ir] += alpha * ( A->val[iptr*9+1]*in[ic] + A->val[iptr*9+4]*in[1+ic] + A->val[iptr*9+7]*in[2+ic] );  
           out[2+3*ir] += alpha * ( A->val[iptr*9+2]*in[ic] + A->val[iptr*9+5]*in[1+ic] + A->val[iptr*9+8]*in[2+ic] );  
       }  
     }  
     } else {  
         /* TODO: parallelize */  
         #pragma omp single  
     for (ic=0;ic< A->pattern->n_ptr;ic++) {  
       for (iptr=A->pattern->ptr[ic]-1;iptr<A->pattern->ptr[ic+1]-1; iptr++) {  
         for (irb=0;irb< A->row_block_size;irb++) {  
           irow=irb+A->row_block_size*(A->pattern->index[iptr]-1);  
           for (icb=0;icb< A->col_block_size;icb++) {  
         icol=icb+A->col_block_size*ic;  
         out[irow] += alpha * A->val[iptr*A->block_size+irb+A->row_block_size*icb] * in[icol];  
           }  
         }  
       }  
     }  
     }  
   }  
   return;  
77  }  }
78    
79  void  Paso_SystemMatrix_MatrixVector_CSR_OFFSET0(double alpha,  void  Paso_SystemMatrix_MatrixVector_CSR_OFFSET0(double alpha,
80      Paso_SystemMatrix* A,                                                   Paso_SystemMatrix* A,
81      double* in,                                                   double* in,
82      double beta,                                                   double beta,
83      double* out) {                                                   double* out)
84    {
85    register index_t ir,icol,iptr,icb,irb,irow,ic,Aiptr;    double *remote_values=NULL;
86    register double reg,reg1,reg2,reg3,in1,in2,in3,A00,A10,A20,A01,A11,A21,A02,A12,A22;    /* start exchange */
87    #pragma omp barrier    Paso_SystemMatrix_startCollect(A,in);
88    if (ABS(beta)>0.) {    /* process main block */
89      #pragma omp for private(irow) schedule(static)    Paso_SparseMatrix_MatrixVector_CSR_OFFSET0(alpha,A->mainBlock,in,beta,out);
90      for (irow=0;irow < A->num_rows * A->row_block_size;irow++)    /* finish exchange */
91        out[irow] *= beta;    remote_values=Paso_SystemMatrix_finishCollect(A);
92    } else {    /* process couple block */
93      #pragma omp for private(irow) schedule(static)    Paso_SparseMatrix_MatrixVector_CSR_OFFSET0(alpha,A->coupleBlock,remote_values,1.,out);
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] = 0;  
   }  
   /*  do the operation: */  
   if (ABS(alpha)>0) {  
     if (A ->col_block_size==1 && A->row_block_size ==1) {  
         #pragma omp for private(irow,iptr,reg) schedule(static)  
     for (irow=0;irow< A->pattern->n_ptr;++irow) {  
           reg=0.;  
       for (iptr=(A->pattern->ptr[irow]);iptr<(A->pattern->ptr[irow+1]); ++iptr) {  
           reg += A->val[iptr] * in[A->pattern->index[iptr]];  
       }  
       out[irow] += alpha * reg;  
     }  
     } else if (A ->col_block_size==2 && A->row_block_size ==2) {  
         #pragma omp for private(ir,reg1,reg2,iptr,ic,Aiptr,in1,in2,A00,A10,A01,A11) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
           reg1=0.;  
           reg2=0.;  
       for (iptr=A->pattern->ptr[ir];iptr<A->pattern->ptr[ir+1]; iptr++) {  
            ic=2*(A->pattern->index[iptr]);  
                Aiptr=iptr*4;  
                in1=in[ic];  
                in2=in[1+ic];  
                A00=A->val[Aiptr  ];  
                A10=A->val[Aiptr+1];  
                A01=A->val[Aiptr+2];  
                A11=A->val[Aiptr+3];  
            reg1 += A00*in1 + A01*in2;  
            reg2 += A10*in1 + A11*in2;  
       }  
       out[  2*ir] += alpha * reg1;  
       out[1+2*ir] += alpha * reg2;  
     }  
     } else if (A ->col_block_size==3 && A->row_block_size ==3) {  
         #pragma omp for private(ir,reg1,reg2,reg3,iptr,ic,Aiptr,in1,in2,in3,A00,A10,A20,A01,A11,A21,A02,A12,A22) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
           reg1=0.;  
           reg2=0.;  
           reg3=0.;  
       for (iptr=A->pattern->ptr[ir];iptr<A->pattern->ptr[ir+1]; iptr++) {  
            ic=3*(A->pattern->index[iptr]);  
                Aiptr=iptr*9;  
                in1=in[ic];  
                in2=in[1+ic];  
                in3=in[2+ic];  
                A00=A->val[Aiptr  ];  
                A10=A->val[Aiptr+1];  
                A20=A->val[Aiptr+2];  
                A01=A->val[Aiptr+3];  
                A11=A->val[Aiptr+4];  
                A21=A->val[Aiptr+5];  
                A02=A->val[Aiptr+6];  
                A12=A->val[Aiptr+7];  
                A22=A->val[Aiptr+8];  
            reg1 += A00*in1 + A01*in2 + A02*in3;  
            reg2 += A10*in1 + A11*in2 + A12*in3;  
            reg3 += A20*in1 + A21*in2 + A22*in3;  
       }  
       out[  3*ir] += alpha * reg1;  
       out[1+3*ir] += alpha * reg2;  
       out[2+3*ir] += alpha * reg3;  
     }  
     } else {  
         #pragma omp for private(ir,iptr,irb,icb,irow,icol,reg) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
       for (iptr=A->pattern->ptr[ir];iptr<A->pattern->ptr[ir+1]; iptr++) {  
         for (irb=0;irb< A->row_block_size;irb++) {  
           irow=irb+A->row_block_size*ir;  
               reg=0.;  
           for (icb=0;icb< A->col_block_size;icb++) {  
         icol=icb+A->col_block_size*(A->pattern->index[iptr]);  
         reg += A->val[iptr*A->block_size+irb+A->row_block_size*icb] * in[icol];  
           }  
           out[irow] += alpha * reg;  
         }  
       }  
     }  
     }  
   }  
   return;  
94  }  }
   
 void  Paso_SystemMatrix_MatrixVector_CSR_OFFSET1(double alpha,  
     Paso_SystemMatrix* A,  
     double* in,  
     double beta,  
     double* out) {  
   
   register index_t ir,icol,iptr,icb,irb,irow,ic;  
   register double reg,reg1,reg2,reg3;  
   #pragma omp barrier  
   
   if (ABS(beta)>0.) {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] *= beta;  
   } else {  
     #pragma omp for private(irow) schedule(static)  
     for (irow=0;irow < A->num_rows * A->row_block_size;irow++)  
       out[irow] = 0;  
   }  
   /*  do the operation: */  
   if (ABS(alpha)>0) {  
     if (A ->col_block_size==1 && A->row_block_size ==1) {  
         #pragma omp for private(irow,iptr,reg) schedule(static)  
     for (irow=0;irow< A->pattern->n_ptr;++irow) {  
           reg=0.;  
       for (iptr=(A->pattern->ptr[irow])-1;iptr<(A->pattern->ptr[irow+1])-1; ++iptr) {  
           reg += A->val[iptr] * in[A->pattern->index[iptr]-1];  
       }  
       out[irow] += alpha * reg;  
     }  
     } else if (A ->col_block_size==2 && A->row_block_size ==2) {  
         #pragma omp for private(ir,reg1,reg2,iptr,ic) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
           reg1=0.;  
           reg2=0.;  
       for (iptr=A->pattern->ptr[ir]-1;iptr<A->pattern->ptr[ir+1]-1; iptr++) {  
            ic=2*(A->pattern->index[iptr]-1);  
            reg1 += A->val[iptr*4  ]*in[ic] + A->val[iptr*4+2]*in[1+ic];  
            reg2 += A->val[iptr*4+1]*in[ic] + A->val[iptr*4+3]*in[1+ic];  
       }  
       out[  2*ir] += alpha * reg1;  
       out[1+2*ir] += alpha * reg2;  
     }  
     } else if (A ->col_block_size==3 && A->row_block_size ==3) {  
         #pragma omp for private(ir,reg1,reg2,reg3,iptr,ic) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
           reg1=0.;  
           reg2=0.;  
           reg3=0.;  
       for (iptr=A->pattern->ptr[ir]-1;iptr<A->pattern->ptr[ir+1]-1; iptr++) {  
            ic=3*(A->pattern->index[iptr]-1);  
            reg1 += A->val[iptr*9  ]*in[ic] + A->val[iptr*9+3]*in[1+ic] + A->val[iptr*9+6]*in[2+ic];  
            reg2 += A->val[iptr*9+1]*in[ic] + A->val[iptr*9+4]*in[1+ic] + A->val[iptr*9+7]*in[2+ic];  
            reg3 += A->val[iptr*9+2]*in[ic] + A->val[iptr*9+5]*in[1+ic] + A->val[iptr*9+8]*in[2+ic];  
       }  
       out[  3*ir] += alpha * reg1;  
       out[1+3*ir] += alpha * reg2;  
       out[2+3*ir] += alpha * reg3;  
     }  
     } else {  
         #pragma omp for private(ir,iptr,irb,icb,irow,icol,reg) schedule(static)  
     for (ir=0;ir< A->pattern->n_ptr;ir++) {  
       for (iptr=A->pattern->ptr[ir]-1;iptr<A->pattern->ptr[ir+1]-1; iptr++) {  
         for (irb=0;irb< A->row_block_size;irb++) {  
           irow=irb+A->row_block_size*ir;  
               reg=0.;  
           for (icb=0;icb< A->col_block_size;icb++) {  
         icol=icb+A->col_block_size*(A->pattern->index[iptr]-1);  
         reg += A->val[iptr*A->block_size+irb+A->row_block_size*icb] * in[icol];  
           }  
           out[irow] += alpha * reg;  
         }  
       }  
     }  
     }  
   }  
   return;  
 }  
 /*  
  * $Log$  
  * Revision 1.2  2005/09/15 03:44:39  jgs  
  * Merge of development branch dev-02 back to main trunk on 2005-09-15  
  *  
  * Revision 1.1.2.1  2005/09/05 06:29:47  gross  
  * These files have been extracted from finley to define a stand alone libray for iterative  
  * linear solvers on the ALTIX. main entry through Paso_solve. this version compiles but  
  * has not been tested yet.  
  *  
  *  
  */  

Legend:
Removed from v.633  
changed lines
  Added in v.1384

  ViewVC Help
Powered by ViewVC 1.1.26