QUDA v0.3.2
A library for QCD on GPUs

quda/lib/cpu_color_spinor_field.cpp

Go to the documentation of this file.
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 &param) :
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines