QUDA v0.4.0
A library for QCD on GPUs
quda/tests/domain_wall_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 <domain_wall_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] = 16; 
00027   gauge_param.X[1] = 16;
00028   gauge_param.X[2] = 16;
00029   gauge_param.X[3] = 16;
00030   inv_param.Ls = 16;
00031 
00032   gauge_param.anisotropy = 1.0;
00033   gauge_param.type = QUDA_WILSON_LINKS;
00034   gauge_param.gauge_order = QUDA_QDP_GAUGE_ORDER;
00035   gauge_param.t_boundary = QUDA_ANTI_PERIODIC_T;
00036   
00037   gauge_param.cpu_prec = cpu_prec;
00038   gauge_param.cuda_prec = cuda_prec;
00039   gauge_param.reconstruct = QUDA_RECONSTRUCT_12;
00040   gauge_param.cuda_prec_sloppy = cuda_prec_sloppy;
00041   gauge_param.reconstruct_sloppy = QUDA_RECONSTRUCT_12;
00042   gauge_param.gauge_fix = QUDA_GAUGE_FIXED_NO;
00043 
00044   inv_param.dslash_type = QUDA_DOMAIN_WALL_DSLASH;
00045   inv_param.inv_type = QUDA_CG_INVERTER;
00046 
00047   inv_param.mass = 0.01;
00048   inv_param.m5 = -1.5;
00049   double kappa5 = 0.5/(5 + inv_param.m5);
00050 
00051   inv_param.tol = 5e-8;
00052   inv_param.maxiter = 1000;
00053   inv_param.reliable_delta = 0.1;
00054 
00055   inv_param.solution_type = QUDA_MAT_SOLUTION;
00056   inv_param.solve_type = QUDA_NORMEQ_PC_SOLVE;
00057   inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN;
00058   inv_param.dagger = QUDA_DAG_NO;
00059   inv_param.mass_normalization = QUDA_KAPPA_NORMALIZATION;
00060 
00061   inv_param.cpu_prec = cpu_prec;
00062   inv_param.cuda_prec = cuda_prec;
00063   inv_param.cuda_prec_sloppy = cuda_prec_sloppy;
00064   inv_param.prec_precondition = cuda_prec_sloppy;
00065   inv_param.preserve_source = QUDA_PRESERVE_SOURCE_NO;
00066   inv_param.gamma_basis = QUDA_DEGRAND_ROSSI_GAMMA_BASIS;
00067   inv_param.dirac_order = QUDA_DIRAC_ORDER;
00068 
00069   inv_param.tune = QUDA_TUNE_YES;
00070 
00071   gauge_param.ga_pad = 0; // 24*24*24;
00072   inv_param.sp_pad = 0;   // 24*24*24;
00073   inv_param.cl_pad = 0;   // 24*24*24;
00074 
00075   inv_param.verbosity = QUDA_VERBOSE;
00076 
00077   // Everything between here and the call to initQuda() is application-specific.
00078 
00079   // set parameters for the reference Dslash, and prepare fields to be loaded
00080   setDims(gauge_param.X, inv_param.Ls);
00081 
00082   size_t gSize = (gauge_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
00083   size_t sSize = (inv_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
00084 
00085   void *gauge[4];
00086 
00087   for (int dir = 0; dir < 4; dir++) {
00088     gauge[dir] = malloc(V*gaugeSiteSize*gSize);
00089   }
00090   construct_gauge_field(gauge, 1, gauge_param.cpu_prec, &gauge_param);
00091 
00092   void *spinorIn = malloc(V*spinorSiteSize*sSize*inv_param.Ls);
00093   void *spinorOut = malloc(V*spinorSiteSize*sSize*inv_param.Ls);
00094   void *spinorCheck = malloc(V*spinorSiteSize*sSize*inv_param.Ls);
00095 
00096   // create a point source at 0
00097   if (inv_param.cpu_prec == QUDA_SINGLE_PRECISION) *((float*)spinorIn) = 1.0;
00098   else *((double*)spinorIn) = 1.0;
00099 
00100   // start the timer
00101   double time0 = -((double)clock());
00102 
00103   // initialize the QUDA library
00104   initQuda(device);
00105 
00106   // load the gauge field
00107   loadGaugeQuda((void*)gauge, &gauge_param);
00108 
00109   // perform the inversion
00110   invertQuda(spinorOut, spinorIn, &inv_param);
00111 
00112   // stop the timer
00113   time0 += clock();
00114   time0 /= CLOCKS_PER_SEC;
00115 
00116   printf("Device memory used:\n   Spinor: %f GiB\n    Gauge: %f GiB\n", 
00117          inv_param.spinorGiB, gauge_param.gaugeGiB);
00118   printf("\nDone: %i iter / %g secs = %g Gflops, total time = %g secs\n", 
00119          inv_param.iter, inv_param.secs, inv_param.gflops/inv_param.secs, time0);
00120 
00121   if (inv_param.solution_type == QUDA_MAT_SOLUTION) { 
00122     mat(spinorCheck, gauge, spinorOut, kappa5, 0, inv_param.cpu_prec, 
00123         gauge_param.cpu_prec, inv_param.mass); 
00124     if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION)
00125       ax(0.5/kappa5, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00126   } else if(inv_param.solution_type == QUDA_MATPC_SOLUTION) {   
00127     matpc(spinorCheck, gauge, spinorOut, kappa5, inv_param.matpc_type, 0, 
00128           inv_param.cpu_prec, gauge_param.cpu_prec, inv_param.mass);
00129     if (inv_param.mass_normalization == QUDA_MASS_NORMALIZATION)
00130       ax(0.25/(kappa5*kappa5), spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00131   }
00132 
00133   mxpy(spinorIn, spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00134   double nrm2 = norm_2(spinorCheck, V*spinorSiteSize, inv_param.cpu_prec);
00135   double src2 = norm_2(spinorIn, V*spinorSiteSize, inv_param.cpu_prec);
00136   printf("Relative residual: requested = %g, actual = %g\n", inv_param.tol, sqrt(nrm2/src2));
00137 
00138   // finalize the QUDA library
00139   endQuda();
00140 
00141   return 0;
00142 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines