/* File: r_vector.c */ #include "r_vector.h" /* * The r_vector is the basic data structure for * representing flux or pressure nodal values. * An r_vector structure contains a pointer * to a double vector and a ponter to an r_data structure. * * The r_data structure contains the length of the * double vector and the number of elements in the * x-direstion (l), y-direstion (m) and z-direction (n). * * Several r_vector functions are defined for * adding, subtracting, multiply add, etc. * Many of these functions use loop unrolling * to maximize cache efficiency. * */ int r_allocate(r_vector* r_ptr, r_data* rdp) { r_ptr->vec=(double*)calloc(rdp->neq,sizeof(double)); if(r_ptr->vec==NULL) return 0; r_ptr->rdp=rdp; return sizeof(double)*rdp->neq; } void r_free(r_vector* r_ptr) { if(r_ptr->vec!=NULL) free(r_ptr->vec); r_ptr->vec=NULL; } /* BLAS-like functions */ double r_dotprd(r_vector* r1_ptr, r_vector* r2_ptr) { double dot; double *r1,*r2; int i,m,neq; neq=r1_ptr->rdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; dot = 0.0; m=neq%4; for(i=0;irdp->neq; r=r_ptr->vec; if(neq<=0) return 0; m=neq%4; for(i=0;irdp->neq; r=r_ptr->vec; if(neq<=0) return 0; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; m=neq%4; for(i=0;irdp->neq; if(neq<=0) return 0; if(neq!=r2_ptr->rdp->neq) return 0; if(neq!=r3_ptr->rdp->neq) return 0; r1=r1_ptr->vec; r2=r2_ptr->vec; r3=r3_ptr->vec; m=neq%4; for(i=0;ivec; r2= r2_ptr->vec; neq=r1_ptr->rdp->neq; for(i= 0;ivec; neq=r_ptr->rdp->neq; if(seed==0) for(i=0;irdp->neq; r=r_ptr->vec; for(i=0;irdp->l; m=r_ptr->rdp->m; n=r_ptr->rdp->n; lm=l*m; r=r_ptr->vec; klm=0; for(k=0;krdp,sizeof(r_data),1,fp); fwrite((double *) r_ptr->vec,sizeof(double),r_ptr->rdp->neq,fp); fflush(fp); return 1; } double r_max_error(r_vector* r1_ptr, r_vector* r2_ptr) /* * computes max|r1-r2| */ { int i; int neq; double* r1,*r2; double e,Max_e; neq=r1_ptr->rdp->neq; r1=r1_ptr->vec; r2=r2_ptr->vec; Max_e=0.0; for(i=0;iMax_e) Max_e=e; } return Max_e; } double r_max(r_vector* r_ptr) /* * computes ri s.t. |ri|>=rj for all j. */ { int i; int neq; double* r; double e,Max_e; neq=r_ptr->rdp->neq; r=r_ptr->vec; Max_e=r[0]; for(i=0;ifabs(Max_e)) Max_e=e; } return Max_e; } int GEN_assemble(GEN_operator* G_ptr, void* A_ptr, int (*A_eval)(r_vector*,r_vector*,void*), void (*A_free)(void*)) { G_ptr->A_ptr=A_ptr; G_ptr->A_eval=A_eval; G_ptr->A_free=A_free; return 1; } void GEN_free(GEN_operator* G_ptr) { if(G_ptr->A_free != NULL) (*G_ptr->A_free)(G_ptr->A_ptr); } int GEN_eval(r_vector* r2_ptr, r_vector* r1_ptr, GEN_operator* G_ptr) { if(G_ptr->A_eval==NULL) { r_copy(r2_ptr,r1_ptr); return 0; } return (*G_ptr->A_eval)(r2_ptr,r1_ptr,G_ptr->A_ptr); } /* * GEN_write assembles the generic operator to a binary file pointed * to by fp. This is done by repeated evaluation of the coordinate * vector p[i]=1 for i=0,..,neq. * * row_data points to the row-space r_data and col_data points to the * column-space r_data. */ int GEN_write(FILE* fp, GEN_operator* A_ptr, r_data* row_data, r_data* col_data) { r_vector r1,r2; int rows,cols; int i; if(!r_allocate(&r2,row_data)) return 0; if(!r_allocate(&r1,col_data)) return 0; rows=row_data->neq; cols=col_data->neq; fwrite(&rows,sizeof(int),1,fp); fwrite(&cols,sizeof(int),1,fp); for(i=0;i