QUDA v0.3.2
A library for QCD on GPUs

quda/tests/twisted_mass_invert_test.c

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <time.h>
00004 #include <math.h>
00005 
00006 #include <test_util.h>
00007 #include <blas_reference.h>
00008 #include <twisted_mass_dslash_reference.h>
00009 
00010 // In a typical application, quda.h is the only QUDA header required.
00011 #include <quda.h>
00012 
00013 int main(int argc, char **argv)
00014 {
00015   // set QUDA parameters
00016 
00017   int device = 0; // CUDA device number
00018 
00019   QudaPrecision cpu_prec = QUDA_DOUBLE_PRECISION;
00020   QudaPrecision cuda_prec = QUDA_SINGLE_PRECISION;
00021   QudaPrecision cuda_prec_sloppy = QUDA_HALF_PRECISION;
00022 
00023   QudaGaugeParam gauge_param = newQudaGaugeParam();
00024   QudaInvertParam inv_param = newQudaInvertParam();
00025  
00026   gauge_param.X[0] = 24; 
00027   gauge_param.X[1] = 24;
00028   gauge_param.X[2] = 24;
00029   gauge_param.X[3] = 24;
00030 
00031   gauge_param.anisotropy = 1.0;
00032   gauge_param.type = QUDA_WILSON_LINKS;
00033   gauge_param.gauge_order = QUDA_QDP_GAUGE_ORDER;
00034   gauge_param.t_boundary = QUDA_ANTI_PERIODIC_T;
00035   
00036   gauge_param.cpu_prec = cpu_prec;
00037   gauge_param.cuda_prec = cuda_prec;
00038   gauge_param.reconstruct = QUDA_RECONSTRUCT_12;
00039   gauge_param.cuda_prec_sloppy = cuda_prec_sloppy;
00040   gauge_param.reconstruct_sloppy = QUDA_RECONSTRUCT_12;
00041   gauge_param.gauge_fix = QUDA_GAUGE_FIXED_NO;
00042 
00043   inv_param.dslash_type = QUDA_TWISTED_MASS_DSLASH;
00044 
00045   inv_param.inv_type = QUDA_CG_INVERTER;
00046 
00047   double mass = -0.9;
00048   inv_param.kappa = 1.0 / (2.0*(1 + 3/gauge_param.anisotropy + mass));
00049   inv_param.mu = 0.1;
00050   inv_param.twist_flavor = QUDA_TWIST_MINUS;
00051 
00052   inv_param.tol = 5e-8;
00053   inv_param.maxiter = 10000;
00054   inv_param.reliable_delta = 1e-2;
00055 
00056   inv_param.solution_type = QUDA_MAT_SOLUTION;
00057   inv_param.solve_type = QUDA_DIRECT_PC_SOLVE;
00058   inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN;
00059   inv_param.dagger = QUDA_DAG_NO;
00060   inv_param.mass_normalization = QUDA_MASS_NORMALIZATION;
00061 
00062   inv_param.cpu_prec = cpu_prec;
00063   inv_param.cuda_prec = cuda_prec;
00064   inv_param.cuda_prec_sloppy = cuda_prec_sloppy;
00065   inv_param.preserve_source = QUDA_PRESERVE_SOURCE_NO;
00066   inv_param.dirac_order = QUDA_DIRAC_ORDER;
00067 
00068   gauge_param.ga_pad = 0; // 24*24*24;
00069   inv_param.sp_pad = 0;   // 24*24*24;
00070   inv_param.cl_pad = 0;   // 24*24*24;
00071 
00072   inv_param.verbosity = QUDA_VERBOSE;
00073 
00074   // Everything between here and the call to initQuda() is application-specific.
00075 
00076   // set parameters for the reference Dslash, and prepare fields to be loaded
00077   setDims(gauge_param.X);
00078 
00079   size_t gSize = (gauge_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
00080   size_t sSize = (inv_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
00081 
00082   void *gauge[4];
00083 
00084   for (int dir = 0; dir < 4; dir++) {
00085     gauge[dir] = malloc(V*gaugeSiteSize*gSize);
00086   }
00087   construct_gauge_field(gauge, 1, gauge_param.cpu_prec, &gauge_param);
00088 
00089   void *spinorIn = malloc(V*spinorSiteSize*sSize);
00090   void *spinorOut = malloc(V*spinorSiteSize*sSize);
00091   void *spinorCheck = malloc(V*spinorSiteSize*sSize);
00092 
00093   // create a point source at 0
00094   if (inv_param.cpu_prec == QUDA_SINGLE_PRECISION) *((float*)spinorIn) = 1.0;
00095   else *((double*)spinorIn) = 1.0;
00096 
00097   // start the timer
00098   double time0 = -((double)clock());
00099 
00100   // initialize the QUDA library
00101   initQuda(device);
00102 
00103   // load the gauge field
00104   loadGaugeQuda((void*)gauge, &gauge_param);
00105 
00106   // perform the inversion
00107   invertQuda(spinorOut, spinorIn, &inv_param);
00108 
00109   // stop the timer
00110   time0 += clock();
00111   time0 /= CLOCKS_PER_SEC;
00112 
00113   printf("Device memory used:\n   Spinor: %f GiB\n    Gauge: %f GiB\n", 
00114          inv_param.spinorGiB, gauge_param.gaugeGiB);
00115   printf("\nDone: %i iter / %g secs = %g Gflops, total time = %g secs\n", 
00116          inv_param.iter, inv_param.secs, inv_param.gflops/inv_param.secs, time0);
00117 
00118   if (inv_param.solution_type == QUDA_MAT_SOLUTION) { 
00119     mat(spinorCheck, gauge, spinorOut, inv_param.kappa, inv_param.mu, inv_param.twist_flavor, 
00120         0, inv_param.cpu_prec, gauge_param.cpu_prec); 
00121     if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION)
00122       ax(0.5/inv_param.kappa, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00123   } else if(inv_param.solution_type == QUDA_MATPC_SOLUTION) {   
00124     matpc(spinorCheck, gauge, spinorOut, inv_param.kappa, inv_param.mu, inv_param.twist_flavor, 
00125           inv_param.matpc_type, 0, inv_param.cpu_prec, gauge_param.cpu_prec);
00126     if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION)
00127       ax(0.25/(inv_param.kappa*inv_param.kappa), spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00128   }
00129 
00130   mxpy(spinorIn, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00131   double nrm2 = norm_2(spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00132   double src2 = norm_2(spinorIn, V*spinorSiteSize, inv_param.cpu_prec);
00133   printf("Relative residual: requested = %g, actual = %g\n", inv_param.tol, sqrt(nrm2/src2));
00134 
00135   // finalize the QUDA library
00136   endQuda();
00137 
00138   return 0;
00139 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines