QUDA v0.4.0
A library for QCD on GPUs
|
00001 #include <color_spinor_field.h> 00002 #include <string.h> 00003 #include <iostream> 00004 #include <face_quda.h> 00005 00006 // forward declarations 00007 double normCpu(const cpuColorSpinorField &b); 00008 double normCuda(const cudaColorSpinorField &b); 00009 00010 00011 /*ColorSpinorField::ColorSpinorField() : init(false) { 00012 00013 }*/ 00014 00015 ColorSpinorParam::ColorSpinorParam(const ColorSpinorField &field) { 00016 field.fill(*this); 00017 } 00018 00019 ColorSpinorField::ColorSpinorField(const ColorSpinorParam ¶m) : verbose(param.verbose), init(false), 00020 even(0), odd(0) 00021 { 00022 create(param.nDim, param.x, param.nColor, param.nSpin, param.twistFlavor, param.precision, param.pad, 00023 param.fieldLocation, param.siteSubset, param.siteOrder, param.fieldOrder, 00024 param.gammaBasis); 00025 00026 } 00027 00028 ColorSpinorField::ColorSpinorField(const ColorSpinorField &field) : verbose(field.verbose), init(false), 00029 even(0), odd(0) 00030 { 00031 create(field.nDim, field.x, field.nColor, field.nSpin, field.twistFlavor, field.precision, field.pad, 00032 field.fieldLocation, field.siteSubset, field.siteOrder, field.fieldOrder, 00033 field.gammaBasis); 00034 00035 } 00036 00037 ColorSpinorField::~ColorSpinorField() { 00038 destroy(); 00039 } 00040 00041 void ColorSpinorField::createGhostZone() { 00042 00043 if (verbose == QUDA_DEBUG_VERBOSE && fieldLocation == QUDA_CUDA_FIELD_LOCATION) 00044 printfQuda("Location = %d, Precision = %d, Subset = %d\n", fieldLocation, precision, siteSubset); 00045 00046 int num_faces = 1; 00047 int num_norm_faces=2; 00048 if (nSpin == 1) { //staggered 00049 num_faces=6; 00050 num_norm_faces=6; 00051 } 00052 00053 // calculate size of ghost zone required 00054 int ghostVolume = 0; 00055 for (int i=0; i<nDim; i++) { 00056 ghostFace[i] = 0; 00057 if (commDimPartitioned(i)) { 00058 ghostFace[i] = 1; 00059 for (int j=0; j<nDim; j++) { 00060 if (i==j) continue; 00061 ghostFace[i] *= x[j]; 00062 } 00063 if (i==0 && siteSubset != QUDA_FULL_SITE_SUBSET) ghostFace[i] /= 2; 00064 if (siteSubset == QUDA_FULL_SITE_SUBSET) ghostFace[i] /= 2; 00065 ghostVolume += ghostFace[i]; 00066 } 00067 if(i==0){ 00068 ghostOffset[i] = 0; 00069 ghostNormOffset[i] = 0; 00070 }else{ 00071 ghostOffset[i] = ghostOffset[i-1] + num_faces*ghostFace[i-1]; 00072 ghostNormOffset[i] = ghostNormOffset[i-1] + num_norm_faces*ghostFace[i-1]; 00073 } 00074 00075 if (verbose == QUDA_DEBUG_VERBOSE && fieldLocation == QUDA_CUDA_FIELD_LOCATION) 00076 printfQuda("face %d = %6d commDimPartitioned = %6d ghostOffset = %6d ghostNormOffset = %6d\n", 00077 i, ghostFace[i], commDimPartitioned(i), ghostOffset[i], ghostNormOffset[i]); 00078 } 00079 int ghostNormVolume = num_norm_faces * ghostVolume; 00080 ghostVolume *= num_faces; 00081 00082 if (verbose == QUDA_DEBUG_VERBOSE && fieldLocation == QUDA_CUDA_FIELD_LOCATION) 00083 printfQuda("Allocated ghost volume = %d, ghost norm volume %d\n", ghostVolume, ghostNormVolume); 00084 00085 // ghost zones are calculated on c/b volumes 00086 #ifdef MULTI_GPU 00087 ghost_length = ghostVolume*nColor*nSpin*2; 00088 ghost_norm_length = (precision == QUDA_HALF_PRECISION) ? ghostNormVolume : 0; 00089 #else 00090 ghost_length = 0; 00091 ghost_norm_length = 0; 00092 #endif 00093 00094 if (siteSubset == QUDA_FULL_SITE_SUBSET) { 00095 total_length = length + 2*ghost_length; // 2 ghost zones in a full field 00096 total_norm_length = 2*(stride + ghost_norm_length); // norm length = 2*stride 00097 } else { 00098 total_length = length + ghost_length; 00099 total_norm_length = (precision == QUDA_HALF_PRECISION) ? stride + ghost_norm_length : 0; // norm length = stride 00100 } 00101 00102 // no ghost zones for cpu fields (yet?) 00103 if (fieldLocation == QUDA_CPU_FIELD_LOCATION) { 00104 ghost_length = 0; 00105 ghost_norm_length = 0; 00106 total_length = length; 00107 total_norm_length = (siteSubset == QUDA_FULL_SITE_SUBSET) ? 2*stride : stride; 00108 } 00109 00110 if (precision != QUDA_HALF_PRECISION) total_norm_length = 0; 00111 00112 if (verbose == QUDA_DEBUG_VERBOSE && fieldLocation == QUDA_CUDA_FIELD_LOCATION) { 00113 printfQuda("ghost length = %d, ghost norm length = %d\n", ghost_length, ghost_norm_length); 00114 printfQuda("total length = %d, total norm length = %d\n", total_length, total_norm_length); 00115 } 00116 } 00117 00118 void ColorSpinorField::create(int Ndim, const int *X, int Nc, int Ns, QudaTwistFlavorType Twistflavor, 00119 QudaPrecision Prec, int Pad, QudaFieldLocation fieldLocation, 00120 QudaSiteSubset siteSubset, QudaSiteOrder siteOrder, 00121 QudaFieldOrder fieldOrder, QudaGammaBasis gammaBasis) { 00122 this->fieldLocation = fieldLocation; 00123 this->siteSubset = siteSubset; 00124 this->siteOrder = siteOrder; 00125 this->fieldOrder = fieldOrder; 00126 this->gammaBasis = gammaBasis; 00127 00128 if (Ndim > QUDA_MAX_DIM){ 00129 errorQuda("Number of dimensions nDim = %d too great", Ndim); 00130 } 00131 nDim = Ndim; 00132 nColor = Nc; 00133 nSpin = Ns; 00134 twistFlavor = Twistflavor; 00135 00136 precision = Prec; 00137 volume = 1; 00138 for (int d=0; d<nDim; d++) { 00139 x[d] = X[d]; 00140 volume *= x[d]; 00141 } 00142 pad = Pad; 00143 if (siteSubset == QUDA_FULL_SITE_SUBSET) { 00144 stride = volume/2 + pad; // padding is based on half volume 00145 length = 2*stride*nColor*nSpin*2; 00146 } else { 00147 stride = volume + pad; 00148 length = stride*nColor*nSpin*2; 00149 } 00150 00151 real_length = volume*nColor*nSpin*2; // physical length 00152 00153 createGhostZone(); 00154 00155 bytes = total_length * precision; // includes pads and ghost zones 00156 bytes = ALIGNMENT_ADJUST(bytes); 00157 norm_bytes = total_norm_length * sizeof(float); 00158 norm_bytes = ALIGNMENT_ADJUST(norm_bytes); 00159 init = true; 00160 } 00161 00162 void ColorSpinorField::destroy() { 00163 init = false; 00164 } 00165 00166 ColorSpinorField& ColorSpinorField::operator=(const ColorSpinorField &src) { 00167 if (&src != this) { 00168 create(src.nDim, src.x, src.nColor, src.nSpin, src.twistFlavor, 00169 src.precision, src.pad, src.fieldLocation, src.siteSubset, 00170 src.siteOrder, src.fieldOrder, src.gammaBasis); 00171 } 00172 return *this; 00173 } 00174 00175 // Resets the attributes of this field if param disagrees (and is defined) 00176 void ColorSpinorField::reset(const ColorSpinorParam ¶m) { 00177 00178 if (param.fieldLocation != QUDA_INVALID_FIELD_LOCATION) fieldLocation = param.fieldLocation; 00179 00180 if (param.nColor != 0) nColor = param.nColor; 00181 if (param.nSpin != 0) nSpin = param.nSpin; 00182 if (param.twistFlavor != QUDA_TWIST_INVALID) twistFlavor = param.twistFlavor; 00183 00184 if (param.precision != QUDA_INVALID_PRECISION) precision = param.precision; 00185 if (param.nDim != 0) nDim = param.nDim; 00186 00187 volume = 1; 00188 for (int d=0; d<nDim; d++) { 00189 if (param.x[0] != 0) x[d] = param.x[d]; 00190 volume *= x[d]; 00191 } 00192 00193 if (param.pad != 0) pad = param.pad; 00194 00195 if (param.siteSubset == QUDA_FULL_SITE_SUBSET){ 00196 stride = volume/2 + pad; 00197 length = 2*stride*nColor*nSpin*2; 00198 } else if (param.siteSubset == QUDA_PARITY_SITE_SUBSET){ 00199 stride = volume + pad; 00200 length = stride*nColor*nSpin*2; 00201 } else { 00202 //errorQuda("SiteSubset not defined %d", param.siteSubset); 00203 //do nothing, not an error (can't remember why - need to document this sometime! ) 00204 } 00205 00206 if (param.siteSubset != QUDA_INVALID_SITE_SUBSET) siteSubset = param.siteSubset; 00207 if (param.siteOrder != QUDA_INVALID_SITE_ORDER) siteOrder = param.siteOrder; 00208 if (param.fieldOrder != QUDA_INVALID_FIELD_ORDER) fieldOrder = param.fieldOrder; 00209 if (param.gammaBasis != QUDA_INVALID_GAMMA_BASIS) gammaBasis = param.gammaBasis; 00210 00211 createGhostZone(); 00212 00213 real_length = volume*nColor*nSpin*2; 00214 00215 bytes = total_length * precision; 00216 bytes = ALIGNMENT_ADJUST(bytes); 00217 norm_bytes = total_norm_length * sizeof(float); 00218 norm_bytes = ALIGNMENT_ADJUST(norm_bytes); 00219 if (!init) errorQuda("Shouldn't be resetting a non-inited field\n"); 00220 } 00221 00222 // Fills the param with the contents of this field 00223 void ColorSpinorField::fill(ColorSpinorParam ¶m) const { 00224 param.nColor = nColor; 00225 param.nSpin = nSpin; 00226 param.twistFlavor = twistFlavor; 00227 param.precision = precision; 00228 param.nDim = nDim; 00229 memcpy(param.x, x, QUDA_MAX_DIM*sizeof(int)); 00230 param.pad = pad; 00231 param.fieldLocation = fieldLocation; 00232 param.siteSubset = siteSubset; 00233 param.siteOrder = siteOrder; 00234 param.fieldOrder = fieldOrder; 00235 param.gammaBasis = gammaBasis; 00236 param.create = QUDA_INVALID_FIELD_CREATE; 00237 param.verbose = verbose; 00238 } 00239 00240 // For kernels with precision conversion built in 00241 void ColorSpinorField::checkField(const ColorSpinorField &a, const ColorSpinorField &b) { 00242 if (a.Length() != b.Length()) { 00243 errorQuda("checkSpinor: lengths do not match: %d %d", a.Length(), b.Length()); 00244 } 00245 00246 if (a.Ncolor() != b.Ncolor()) { 00247 errorQuda("checkSpinor: colors do not match: %d %d", a.Ncolor(), b.Ncolor()); 00248 } 00249 00250 if (a.Nspin() != b.Nspin()) { 00251 errorQuda("checkSpinor: spins do not match: %d %d", a.Nspin(), b.Nspin()); 00252 } 00253 00254 if (a.TwistFlavor() != b.TwistFlavor()) { 00255 errorQuda("checkSpinor: twist flavors do not match: %d %d", a.TwistFlavor(), b.TwistFlavor()); 00256 } 00257 } 00258 00259 double norm2(const ColorSpinorField &a) { 00260 00261 double rtn = 0.0; 00262 if (a.FieldLocation() == QUDA_CUDA_FIELD_LOCATION) { 00263 rtn = normCuda(dynamic_cast<const cudaColorSpinorField&>(a)); 00264 } else if (a.FieldLocation() == QUDA_CPU_FIELD_LOCATION) { 00265 rtn = normCpu(dynamic_cast<const cpuColorSpinorField&>(a)); 00266 } else { 00267 errorQuda("Field type %d not supported", a.FieldLocation()); 00268 } 00269 00270 return rtn; 00271 } 00272 00273 std::ostream& operator<<(std::ostream &out, const ColorSpinorField &a) { 00274 out << "fieldLocation = " << a.fieldLocation << std::endl; 00275 out << "nColor = " << a.nColor << std::endl; 00276 out << "nSpin = " << a.nSpin << std::endl; 00277 out << "twistFlavor = " << a.twistFlavor << std::endl; 00278 out << "nDim = " << a.nDim << std::endl; 00279 for (int d=0; d<a.nDim; d++) out << "x[" << d << "] = " << a.x[d] << std::endl; 00280 out << "volume = " << a.volume << std::endl; 00281 out << "precision = " << a.precision << std::endl; 00282 out << "pad = " << a.pad << std::endl; 00283 out << "stride = " << a.stride << std::endl; 00284 out << "real_length = " << a.real_length << std::endl; 00285 out << "length = " << a.length << std::endl; 00286 out << "ghost_length = " << a.ghost_length << std::endl; 00287 out << "total_length = " << a.total_length << std::endl; 00288 out << "ghost_norm_length = " << a.ghost_norm_length << std::endl; 00289 out << "total_norm_length = " << a.total_norm_length << std::endl; 00290 out << "siteSubset = " << a.siteSubset << std::endl; 00291 out << "siteOrder = " << a.siteOrder << std::endl; 00292 out << "fieldOrder = " << a.fieldOrder << std::endl; 00293 out << "gammaBasis = " << a.gammaBasis << std::endl; 00294 return out; 00295 }