|
QUDA v0.3.2
A library for QCD on GPUs
|
00001 #include <stdlib.h> 00002 #include <stdio.h> 00003 #include <string.h> 00004 #include <iostream> 00005 #include <color_spinor_field.h> 00006 00007 /* 00008 Maybe this will be useful at some point 00009 00010 #define myalloc(type, n, m0) (type *) aligned_malloc(n*sizeof(type), m0) 00011 00012 #define ALIGN 16 00013 void * 00014 aligned_malloc(size_t n, void **m0) 00015 { 00016 size_t m = (size_t) malloc(n+ALIGN); 00017 *m0 = (void*)m; 00018 size_t r = m % ALIGN; 00019 if(r) m += (ALIGN - r); 00020 return (void *)m; 00021 } 00022 */ 00023 00024 /*cpuColorSpinorField::cpuColorSpinorField() : 00025 ColorSpinorField(), init(false) { 00026 00027 }*/ 00028 00029 cpuColorSpinorField::cpuColorSpinorField(const ColorSpinorParam ¶m) : 00030 ColorSpinorField(param), init(false) { 00031 create(param.create); 00032 if (param.create == QUDA_NULL_FIELD_CREATE) { 00033 // do nothing 00034 } else if (param.create == QUDA_ZERO_FIELD_CREATE) { 00035 zero(); 00036 } else if (param.create == QUDA_REFERENCE_FIELD_CREATE) { 00037 v = param.v; 00038 } else { 00039 errorQuda("Creation type not supported"); 00040 } 00041 } 00042 00043 cpuColorSpinorField::cpuColorSpinorField(const cpuColorSpinorField &src) : 00044 ColorSpinorField(src), init(false) { 00045 create(QUDA_COPY_FIELD_CREATE); 00046 memcpy(v,src.v,bytes); 00047 } 00048 00049 cpuColorSpinorField::cpuColorSpinorField(const ColorSpinorField &src) : 00050 ColorSpinorField(src), init(false) { 00051 create(QUDA_COPY_FIELD_CREATE); 00052 if (src.FieldLocation() == QUDA_CPU_FIELD_LOCATION) { 00053 memcpy(v, dynamic_cast<const cpuColorSpinorField&>(src).v, bytes); 00054 } else if (src.FieldLocation() == QUDA_CUDA_FIELD_LOCATION) { 00055 dynamic_cast<const cudaColorSpinorField&>(src).saveCPUSpinorField(*this); 00056 } else { 00057 errorQuda("FieldType not supported"); 00058 } 00059 } 00060 00061 cpuColorSpinorField::~cpuColorSpinorField() { 00062 destroy(); 00063 } 00064 00065 cpuColorSpinorField& cpuColorSpinorField::operator=(const cpuColorSpinorField &src) { 00066 if (&src != this) { 00067 destroy(); 00068 // keep current attributes unless unset 00069 if (!ColorSpinorField::init) ColorSpinorField::operator=(src); 00070 fieldLocation = QUDA_CPU_FIELD_LOCATION; 00071 create(QUDA_COPY_FIELD_CREATE); 00072 copy(src); 00073 } 00074 return *this; 00075 } 00076 00077 cpuColorSpinorField& cpuColorSpinorField::operator=(const cudaColorSpinorField &src) { 00078 destroy(); 00079 // keep current attributes unless unset 00080 if (!ColorSpinorField::init) ColorSpinorField::operator=(src); 00081 fieldLocation = QUDA_CPU_FIELD_LOCATION; 00082 create(QUDA_COPY_FIELD_CREATE); 00083 src.saveCPUSpinorField(*this); 00084 return *this; 00085 } 00086 00087 void cpuColorSpinorField::create(const QudaFieldCreate create) { 00088 if (pad != 0) { 00089 errorQuda("Non-zero pad not supported"); 00090 } 00091 00092 if (precision == QUDA_HALF_PRECISION) { 00093 errorQuda("Half precision not supported"); 00094 } 00095 00096 if (gammaBasis != QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00097 errorQuda("Basis not implemented"); 00098 } 00099 00100 if (fieldOrder != QUDA_SPACE_COLOR_SPIN_FIELD_ORDER && 00101 fieldOrder != QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00102 errorQuda("Field order %d not supported", fieldOrder); 00103 } 00104 00105 if (create != QUDA_REFERENCE_FIELD_CREATE) { 00106 v = (void*)malloc(bytes); 00107 init = true; 00108 } 00109 00110 } 00111 00112 void cpuColorSpinorField::destroy() { 00113 00114 if (init) { 00115 free(v); 00116 init = false; 00117 } 00118 00119 } 00120 00121 void cpuColorSpinorField::copy(const cpuColorSpinorField &src) { 00122 checkField(*this, src); 00123 if (fieldOrder == src.fieldOrder) { 00124 memcpy(v, src.v, bytes); 00125 } else { 00126 errorQuda("Copying between CPU fields with different color/spin ordering is not supported"); 00127 } 00128 } 00129 00130 void cpuColorSpinorField::zero() { 00131 memset(v, '0', bytes); 00132 } 00133 00134 /* 00135 cpuColorSpinorField& cpuColorSpinorField::Even() const { 00136 if (subset == QUDA_FULL_FIELD_SUBSET) { 00137 return *(dynamic_cast<cpuColorSpinorField*>(even)); 00138 } else { 00139 errorQuda("Cannot return even subset of %d subset", subset); 00140 } 00141 } 00142 00143 cpuColorSpinorField& cpuColorSpinorField::Odd() const { 00144 if (subset == QUDA_FULL_FIELD_SUBSET) { 00145 return *(dynamic_cast<cpuColorSpinorField*>(odd)); 00146 } else { 00147 errorQuda("Cannot return odd subset of %d subset", subset); 00148 } 00149 } 00150 */ 00151 00152 //sets the elements of the field to random [0, 1] 00153 template <typename Float> 00154 void random(Float *v, const int length) { 00155 for(int i = 0; i < length; i++) { 00156 v[i] = rand() / (double)RAND_MAX; 00157 } 00158 } 00159 00160 // create a point source at spacetime point st, spin s and colour c 00161 template <typename Float> 00162 void point(Float *v, const int st, const int s, const int c, const int nSpin, 00163 const int nColor, const QudaFieldOrder fieldOrder) { 00164 switch(fieldOrder) { 00165 case QUDA_SPACE_SPIN_COLOR_FIELD_ORDER: 00166 v[(st*nSpin+s)*nColor+c] = 1.0; 00167 break; 00168 case QUDA_SPACE_COLOR_SPIN_FIELD_ORDER: 00169 v[(st*nColor+c)*nSpin+s] = 1.0; 00170 break; 00171 default: 00172 errorQuda("Field ordering %d not supported", fieldOrder); 00173 } 00174 } 00175 00176 void cpuColorSpinorField::Source(const QudaSourceType sourceType, const int st, const int s, const int c) { 00177 00178 switch(sourceType) { 00179 00180 case QUDA_RANDOM_SOURCE: 00181 if (precision == QUDA_DOUBLE_PRECISION) random((double*)v, length); 00182 else if (precision == QUDA_SINGLE_PRECISION) random((float*)v, length); 00183 else errorQuda("Precision not supported"); 00184 break; 00185 00186 case QUDA_POINT_SOURCE: 00187 if (precision == QUDA_DOUBLE_PRECISION) point((double*)v, st, s, c, nSpin, nColor, fieldOrder); 00188 else if (precision == QUDA_SINGLE_PRECISION) point((float*)v, st, s, c, nSpin, nColor, fieldOrder); 00189 else errorQuda("Precision not supported"); 00190 break; 00191 00192 default: 00193 errorQuda("Source type %d not implemented", sourceType); 00194 00195 } 00196 00197 } 00198 00199 template <typename FloatA, typename FloatB> 00200 static void compareSpinor(const FloatA *u, const FloatB *v, const int volume, 00201 const int N, const int resolution) { 00202 int fail_check = 16*resolution; 00203 int *fail = new int[fail_check]; 00204 for (int f=0; f<fail_check; f++) fail[f] = 0; 00205 00206 int *iter = new int[N]; 00207 00208 for (int i=0; i<N; i++) iter[i] = 0; 00209 00210 for (int i=0; i<volume; i++) { 00211 for (int j=0; j<N; j++) { 00212 int is = i*N+j; 00213 double diff = fabs(u[is]-v[is]); 00214 for (int f=0; f<fail_check; f++) 00215 if (diff > pow(10.0,-(f+1)/(double)resolution)) fail[f]++; 00216 if (diff > 1e-3) iter[j]++; 00217 } 00218 } 00219 00220 for (int i=0; i<N; i++) printf("%d fails = %d\n", i, iter[i]); 00221 00222 for (int f=0; f<fail_check; f++) { 00223 printf("%e Failures: %d / %d = %e\n", pow(10.0,-(f+1)/(double)resolution), 00224 fail[f], volume*N, fail[f] / (double)(volume*N)); 00225 } 00226 00227 delete []iter; 00228 delete []fail; 00229 } 00230 00231 void cpuColorSpinorField::Compare(const cpuColorSpinorField &a, const cpuColorSpinorField &b, 00232 const int resolution) { 00233 checkField(a, b); 00234 if (a.precision == QUDA_HALF_PRECISION || b.precision == QUDA_HALF_PRECISION) 00235 errorQuda("Half precision not implemented"); 00236 if (a.fieldOrder != b.fieldOrder || 00237 (a.fieldOrder != QUDA_SPACE_COLOR_SPIN_FIELD_ORDER && a.fieldOrder != QUDA_SPACE_SPIN_COLOR_FIELD_ORDER)) 00238 errorQuda("Field ordering not supported"); 00239 00240 if (a.precision == QUDA_DOUBLE_PRECISION) 00241 if (b.precision == QUDA_DOUBLE_PRECISION) 00242 compareSpinor((double*)a.v, (double*)b.v, a.volume, 2*a.nSpin*a.nColor, resolution); 00243 else 00244 compareSpinor((double*)a.v, (float*)b.v, a.volume, 2*a.nSpin*a.nColor, resolution); 00245 else 00246 if (b.precision == QUDA_DOUBLE_PRECISION) 00247 compareSpinor((float*)a.v, (double*)b.v, a.volume, 2*a.nSpin*a.nColor, resolution); 00248 else 00249 compareSpinor((float*)a.v, (float*)b.v, a.volume, 2*a.nSpin*a.nColor, resolution); 00250 } 00251 00252 template <typename Float> 00253 void print_vector(const Float *v, const int vol, const int Ns, const int Nc, 00254 const QudaFieldOrder fieldOrder) { 00255 00256 switch(fieldOrder) { 00257 00258 case QUDA_SPACE_SPIN_COLOR_FIELD_ORDER: 00259 00260 for (int s=0; s<Ns; s++) { 00261 for (int c=0; c<Nc; c++) { 00262 std::cout << "( " << v[((vol*Ns+s)*Nc+c)*2] << " , " << v[((vol*Ns+s)*Nc+c)*2+1] << " ) "; 00263 } 00264 std::cout << std::endl; 00265 } 00266 break; 00267 00268 case QUDA_SPACE_COLOR_SPIN_FIELD_ORDER: 00269 00270 for (int s=0; s<Ns; s++) { 00271 for (int c=0; c<Nc; c++) { 00272 std::cout << "( " << v[((vol*Nc+c)*Ns+s)*2] << " , " << v[((vol*Nc+c)*Ns+s)*2+1] << " ) "; 00273 } 00274 std::cout << std::endl; 00275 } 00276 break; 00277 00278 default: 00279 errorQuda("Field oredring not supported"); 00280 00281 } 00282 } 00283 00284 // print out the vector at volume point vol 00285 void cpuColorSpinorField::PrintVector(int vol) { 00286 00287 switch(precision) { 00288 case QUDA_DOUBLE_PRECISION: 00289 print_vector((double*)v, vol, nSpin, nColor, fieldOrder); 00290 break; 00291 case QUDA_SINGLE_PRECISION: 00292 print_vector((float*)v, vol, nSpin, nColor, fieldOrder); 00293 break; 00294 default: 00295 errorQuda("Precision %d not implemented", precision); 00296 } 00297 00298 } 00299 00300 double normCpu(const cpuColorSpinorField &a) { 00301 double norm2 = 0.0; 00302 if (a.precision == QUDA_DOUBLE_PRECISION) 00303 for (int i=0; i<a.length; i++) norm2 += ((double*)a.v)[i]*((double*)a.v)[i]; 00304 else if (a.precision == QUDA_SINGLE_PRECISION) 00305 for (int i=0; i<a.length; i++) norm2 += ((float*)a.v)[i]*((float*)a.v)[i]; 00306 else 00307 errorQuda("Precision type %d not implemented", a.precision); 00308 00309 return norm2; 00310 }
1.7.3