QUDA v0.4.0
A library for QCD on GPUs
quda/lib/color_spinor_field.cpp
Go to the documentation of this file.
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 &param) : 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 &param) {
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 &param) 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines