00001
00006 #include "charm++.h"
00007 #include "charm-api.h"
00008 #include "ifemc.h"
00009 #include "ilsi.h"
00010 #include "fem.h"
00011 #include "idxlc.h"
00012
00013
00015 double localDotProduct(int nRecords,int nFields,const unsigned char *goodRecord,
00016 const double *a,const double *b)
00017 {
00018 double sum=0.0;
00019 for (int r=0;r<nRecords;r++)
00020 if (goodRecord[r])
00021 for (int f=0;f<nFields;f++) {
00022 int i=r*nFields+f;
00023 sum+=a[i]*b[i];
00024 }
00025 return sum;
00026 }
00027
00033 class IFEM_Solve_shared_comm : public ILSI_Comm {
00034 int mesh,entity;
00035 const int length,width;
00036 unsigned char *primary;
00037 IDXL_Layout_t shared_fid, reduce_fid;
00038 IDXL_t shared_idxl;
00039
00040
00041 IFEM_Matrix_product_c A_c;
00042 IFEM_Matrix_product_f A_f;
00043 void *ptr;
00044 public:
00045 IFEM_Solve_shared_comm(int mesh_,int entity_, int length_,int width_)
00046 :mesh(mesh_), entity(entity_), length(length_), width(width_),
00047 A_c(0), A_f(0), ptr(0)
00048 {
00049
00050 if (length!=FEM_Mesh_get_length(mesh,entity))
00051 CkAbort("IFEM_Solve_shared: vector length must equal number of nodes!");
00052 if (width<1) CkAbort("IFEM_Solve_shared: number of unknowns per node < 1!");
00053 if (width>100) CkAbort("IFEM_Solve_shared: do you really want that many unknowns per node?");
00054
00055
00056 shared_fid=IDXL_Layout_create(IDXL_DOUBLE,width);
00057 reduce_fid=IDXL_Layout_create(IDXL_DOUBLE,1);
00058 primary=new unsigned char[length];
00059 FEM_Mesh_get_data(mesh,entity,FEM_NODE_PRIMARY, primary,
00060 0,length, FEM_BYTE,1);
00061 shared_idxl=FEM_Comm_shared(mesh,entity);
00062 }
00063
00064
00065 void set_c(IFEM_Matrix_product_c A,void *ptr_) {
00066 A_c=A; ptr=ptr_;
00067 }
00068 void set_f(IFEM_Matrix_product_f A,void *ptr_) {
00069 A_f=A; ptr=ptr_;
00070 }
00071
00073 virtual void matrixVectorProduct(const double *src,double *dest) {
00074
00075 if (A_c) (A_c)(ptr,length,width,src,dest);
00076 else (A_f)(ptr,&length,&width,src,dest);
00077 }
00078
00080 virtual double dotProduct(const double *a,const double *b) {
00081
00082 double sum=localDotProduct(length,width,primary,a,b);
00083
00084 double gsum;
00085 FEM_Reduce(reduce_fid,&sum,&gsum,FEM_SUM);
00086 return gsum;
00087 }
00088
00089 ~IFEM_Solve_shared_comm() {
00090 delete[] primary;
00091 IDXL_Layout_destroy(reduce_fid);
00092 IDXL_Layout_destroy(shared_fid);
00093 }
00094 };
00095
00096 CLINKAGE void
00097 IFEM_Solve_shared(ILSI_Solver s,ILSI_Param *p,
00098 int fem_mesh, int fem_entity,int length,int width,
00099 IFEM_Matrix_product_c A, void *ptr,
00100 const double *b, double *x)
00101 {
00102 IFEM_Solve_shared_comm comm(fem_mesh,fem_entity,length,width);
00103 comm.set_c(A,ptr);
00104
00105 int n=length*width;
00106 (s)(p,&comm,n,b,x);
00107 }
00108
00109 FLINKAGE void
00110 FTN_NAME(IFEM_SOLVE_SHARED,ifem_solve_shared)
00111 (ILSI_Solver s,ILSI_Param *p,
00112 int *fem_mesh, int *fem_entity,int *length,int *width,
00113 IFEM_Matrix_product_f A, void *ptr,
00114 const double *b, double *x)
00115 {
00116 IFEM_Solve_shared_comm comm(*fem_mesh,*fem_entity,*length,*width);
00117 comm.set_f(A,ptr);
00118
00119 int n=*length* *width;
00120 (s)(p,&comm,n,b,x);
00121 }
00122
00123
00124
00137 class BCapplier {
00138
00139 IFEM_Matrix_product_c A_c;
00140 IFEM_Matrix_product_f A_f;
00141 void *ptr;
00142
00143 inline void userMultiply(int length,int width,const double *src,double *dest) {
00144
00145 if (A_c) (A_c)(ptr,length,width,src,dest);
00146 else (A_f)(ptr,&length,&width,src,dest);
00147 }
00148
00154 int bcCount;
00155 int idxBase;
00156 const int *bcDOF;
00157 inline int at(int bcIdx) { return bcDOF[bcIdx]-idxBase; }
00158 const double *bcValue;
00159
00160 public:
00161 BCapplier(int cnt_,int base_,const int *dof_,const double *value_)
00162 :A_c(0), A_f(0), ptr(0), bcCount(cnt_), idxBase(base_),
00163 bcDOF(dof_), bcValue(value_)
00164 {
00165 }
00166
00167
00168 void set_c(IFEM_Matrix_product_c A,void *ptr_) {
00169 A_c=A; ptr=ptr_;
00170 }
00171 void set_f(IFEM_Matrix_product_f A,void *ptr_) {
00172 A_f=A; ptr=ptr_;
00173 }
00174
00175
00176 void solve(ILSI_Solver s,ILSI_Param *p,
00177 int fem_mesh, int fem_entity,int length,int width,
00178 const double *b,double *x);
00179
00180
00181 void multiply(int length,int width,const double *u,double *Au) {
00182 int i;
00183
00184
00185
00186
00187 userMultiply(length,width,u,Au);
00188
00189
00190
00191 for (i=0;i<bcCount;i++) Au[at(i)]=0.0;
00192 }
00193 };
00194
00195 extern "C" void
00196 BCapplier_multiply(void *ptr,int length,int width,const double *src,double *dest)
00197 {
00198 BCapplier *bc=(BCapplier *)ptr;
00199 bc->multiply(length,width,src,dest);
00200 }
00201
00202 void BCapplier::solve(ILSI_Solver s,ILSI_Param *p,
00203 int fem_mesh, int fem_entity,int length,int width,
00204 const double *b,double *x)
00205 {
00206
00207 int i,DOFs=length*width;
00208
00209 double *c=new double[DOFs];
00210 for (i=0;i<DOFs;i++) c[i]=0;
00211 for (i=0;i<bcCount;i++) c[at(i)]=bcValue[i];
00212 double *Ac=new double[DOFs];
00213 userMultiply(length,width,c,Ac);
00214
00215
00216 double *bPrime=c;
00217 for (i=0;i<DOFs;i++) bPrime[i]=b[i]-Ac[i];
00218 delete[] Ac;
00219
00220
00221 for (i=0;i<bcCount;i++) {
00222 x[at(i)]=0.0;
00223 bPrime[at(i)]=0.0;
00224 }
00225
00226
00227 IFEM_Solve_shared(s,p, fem_mesh,fem_entity,length,width,
00228 BCapplier_multiply,this,bPrime,x);
00229
00230 delete[] c;
00231
00232
00233 for (i=0;i<bcCount;i++) x[at(i)]=bcValue[i];
00234 }
00235
00236 CLINKAGE void
00237 IFEM_Solve_shared_bc(ILSI_Solver s,ILSI_Param *p,
00238 int fem_mesh, int fem_entity,int length,int width,
00239 int bcCount, const int *bcDOF, const double *bcValue,
00240 IFEM_Matrix_product_c A, void *ptr,
00241 const double *b, double *x)
00242 {
00243 BCapplier bc(bcCount,0,bcDOF,bcValue);
00244 bc.set_c(A,ptr);
00245 bc.solve(s,p,fem_mesh,fem_entity,length,width,b,x);
00246 }
00247
00248 FLINKAGE void
00249 FTN_NAME(IFEM_SOLVE_SHARED_BC,ifem_solve_shared_bc)
00250 (ILSI_Solver s,ILSI_Param *p,
00251 int *fem_mesh, int *fem_entity,int *length,int *width,
00252 int *bcCount,const int *bcDOF,const double *bcValue,
00253 IFEM_Matrix_product_f A, void *ptr,
00254 const double *b, double *x)
00255 {
00256 BCapplier bc(*bcCount,1,bcDOF,bcValue);
00257 bc.set_f(A,ptr);
00258 bc.solve(s,p,*fem_mesh,*fem_entity,*length,*width,b,x);
00259 }
00260
00261