QUDA  1.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
heatbath_test.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include <quda.h>
6 #include <quda_internal.h>
7 #include <gauge_field.h>
8 
9 #include <comm_quda.h>
10 #include <test_util.h>
11 #include <gauge_tools.h>
12 #include "misc.h"
13 
14 #include <pgauge_monte.h>
15 #include <random_quda.h>
16 #include <unitarization_links.h>
17 
18 #include <qio_field.h>
19 
20 #if defined(QMP_COMMS)
21 #include <qmp.h>
22 #elif defined(MPI_COMMS)
23 #include <mpi.h>
24 #endif
25 
26 
27 
28 #define MAX(a,b) ((a)>(b)?(a):(b))
29 #define DABS(a) ((a)<(0.)?(-(a)):(a))
30 
31 // Wilson, clover-improved Wilson, twisted mass, and domain wall are supported.
32 extern int device;
33 extern int xdim;
34 extern int ydim;
35 extern int zdim;
36 extern int tdim;
37 extern int Lsdim;
38 extern int gridsize_from_cmdline[];
40 extern QudaPrecision prec;
43 extern double anisotropy;
44 extern char latfile[];
45 extern char gauge_outfile[];
46 
47 extern double heatbath_beta_value;
48 extern int heatbath_warmup_steps;
49 extern int heatbath_num_steps;
52 extern bool heatbath_coldstart;
53 
54 extern void usage(char** );
55 
56 
57 namespace quda {
58  extern void setTransferGPU(bool);
59 }
60 
61 void
63 {
64  printfQuda("running the following test:\n");
65 
66  printfQuda("prec sloppy_prec link_recon sloppy_link_recon S_dimension T_dimension Ls_dimension\n");
67  printfQuda("%s %s %s %s %d/%d/%d %d %d\n",
71 
72  printfQuda("Grid partition info: X Y Z T\n");
73  printfQuda(" %d %d %d %d\n",
74  dimPartitioned(0),
75  dimPartitioned(1),
76  dimPartitioned(2),
77  dimPartitioned(3));
78 
79  return ;
80 
81 }
82 
86 
88  gauge_param.X[0] = xdim;
89  gauge_param.X[1] = ydim;
90  gauge_param.X[2] = zdim;
91  gauge_param.X[3] = tdim;
92 
93  gauge_param.anisotropy = anisotropy;
94  gauge_param.tadpole_coeff = 1.0;
95  gauge_param.type = QUDA_WILSON_LINKS;
96  gauge_param.gauge_order = QUDA_QDP_GAUGE_ORDER;
97  gauge_param.t_boundary = QUDA_PERIODIC_T;
98 
99  gauge_param.cpu_prec = cpu_prec;
100 
101  gauge_param.cuda_prec = cuda_prec;
102  gauge_param.reconstruct = link_recon;
103 
104  gauge_param.cuda_prec_sloppy = cuda_prec_sloppy;
106 
107  gauge_param.gauge_fix = QUDA_GAUGE_FIXED_NO;
108 
109  gauge_param.ga_pad = 0;
110  // For multi-GPU, ga_pad must be large enough to store a time-slice
111 #ifdef MULTI_GPU
112  int x_face_size = gauge_param.X[1]*gauge_param.X[2]*gauge_param.X[3]/2;
113  int y_face_size = gauge_param.X[0]*gauge_param.X[2]*gauge_param.X[3]/2;
114  int z_face_size = gauge_param.X[0]*gauge_param.X[1]*gauge_param.X[3]/2;
115  int t_face_size = gauge_param.X[0]*gauge_param.X[1]*gauge_param.X[2]/2;
116  int pad_size =MAX(x_face_size, y_face_size);
117  pad_size = MAX(pad_size, z_face_size);
118  pad_size = MAX(pad_size, t_face_size);
119  gauge_param.ga_pad = pad_size;
120 #endif
121 }
122 
124  using namespace quda;
125  const double unitarize_eps = 1e-14;
126  const double max_error = 1e-10;
127  const int reunit_allow_svd = 1;
128  const int reunit_svd_only = 0;
129  const double svd_rel_error = 1e-6;
130  const double svd_abs_error = 1e-6;
131  setUnitarizeLinksConstants(unitarize_eps, max_error,
132  reunit_allow_svd, reunit_svd_only,
133  svd_rel_error, svd_abs_error);
134 
135  }
136 
138  using namespace quda;
139  int *num_failures_dev = (int*)device_malloc(sizeof(int));
140  int num_failures;
141  cudaMemset(num_failures_dev, 0, sizeof(int));
142  unitarizeLinks(*cudaInGauge, num_failures_dev);
143 
144  cudaMemcpy(&num_failures, num_failures_dev, sizeof(int), cudaMemcpyDeviceToHost);
145  if(num_failures>0) errorQuda("Error in the unitarization\n");
146  device_free(num_failures_dev);
147  }
148 
149 int main(int argc, char **argv)
150 {
151 
152  for (int i = 1; i < argc; i++){
153  if(process_command_line_option(argc, argv, &i) == 0){
154  continue;
155  }
156  printf("ERROR: Invalid option:%s\n", argv[i]);
157  usage(argv);
158  }
159 
162 
163  // initialize QMP/MPI, QUDA comms grid and RNG (test_util.cpp)
164  initComms(argc, argv, gridsize_from_cmdline);
165 
166  // call srand() with a rank-dependent seed
167  initRand();
168 
170 
171  // *** QUDA parameters begin here.
172 
174  setGaugeParam(gauge_param);
175 
176  // *** Everything between here and the call to initQuda() is
177  // *** application-specific.
178 
179  setDims(gauge_param.X);
180 
181  setSpinorSiteSize(24);
182 
183  size_t gSize = (gauge_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
184 
185  void *load_gauge[4];
186 
187  for (int dir = 0; dir < 4; dir++) {
188  load_gauge[dir] = malloc(V*gaugeSiteSize*gSize);
189  }
190 
191  if (strcmp(latfile,"")) { // load in the command line supplied gauge field
192  read_gauge_field(latfile, load_gauge, gauge_param.cpu_prec, gauge_param.X, argc, argv);
193  construct_gauge_field(load_gauge, 2, gauge_param.cpu_prec, &gauge_param);
194  }
195 
196  // start the timer
197  double time0 = -((double)clock());
198 
199  // initialize the QUDA library
200  initQuda(device);
201 
202  {
203  using namespace quda;
204  GaugeFieldParam gParam(0, gauge_param);
205  gParam.pad = 0;
208  gParam.link_type = gauge_param.type;
209  gParam.reconstruct = gauge_param.reconstruct;
210  gParam.order = (gauge_param.cuda_prec == QUDA_DOUBLE_PRECISION || gauge_param.reconstruct == QUDA_RECONSTRUCT_NO )
212  cudaGaugeField *gauge = new cudaGaugeField(gParam);
213 
214  int pad = 0;
215  int y[4];
216  int R[4] = {0,0,0,0};
217  for(int dir=0; dir<4; ++dir) if(comm_dim_partitioned(dir)) R[dir] = 2;
218  for(int dir=0; dir<4; ++dir) y[dir] = gauge_param.X[dir] + 2 * R[dir];
219  GaugeFieldParam gParamEx(y, prec, link_recon,
221  gParamEx.create = QUDA_ZERO_FIELD_CREATE;
222  gParamEx.order = gParam.order;
223  gParamEx.siteSubset = QUDA_FULL_SITE_SUBSET;
224  gParamEx.t_boundary = gParam.t_boundary;
225  gParamEx.nFace = 1;
226  for(int dir=0; dir<4; ++dir) gParamEx.r[dir] = R[dir];
227  cudaGaugeField *gaugeEx = new cudaGaugeField(gParamEx);
228  // CURAND random generator initialization
229  RNG *randstates = new RNG(*gauge, 1234);
230  randstates->Init();
231 
232  int nsteps = heatbath_num_steps;
233  int nwarm = heatbath_warmup_steps;
234  int nhbsteps = heatbath_num_heatbath_per_step;
235  int novrsteps = heatbath_num_overrelax_per_step;
236  bool coldstart = heatbath_coldstart;
237  double beta_value = heatbath_beta_value;
238 
239  printfQuda("Starting heatbath for beta = %f from a %s start\n", beta_value, strcmp(latfile,"") ? "loaded" : (coldstart ? "cold" : "hot"));
240  printfQuda(" %d Heatbath hits and %d overrelaxation hits per step\n", nhbsteps, novrsteps);
241  printfQuda(" %d Warmup steps\n", nwarm);
242  printfQuda(" %d Measurement steps\n", nsteps);
243 
244  if (strcmp(latfile,"")) { // Copy in loaded gauge field
245 
246  printfQuda("Loading the gauge field in %s\n", latfile);
247 
248  loadGaugeQuda(load_gauge, &gauge_param);
249  // Get pointer to internal resident gauge field
251  copyExtendedResidentGaugeQuda((void*)extendedGaugeResident, QUDA_CUDA_FIELD_LOCATION);
252  InitGaugeField(*gaugeEx);
253  copyExtendedGauge(*gaugeEx, *extendedGaugeResident, QUDA_CUDA_FIELD_LOCATION);
254  delete extendedGaugeResident;
255 
256  } else if (link_recon != QUDA_RECONSTRUCT_8 && coldstart) {
257  InitGaugeField( *gaugeEx);
258  } else {
259  InitGaugeField( *gaugeEx, *randstates );
260  }
261 
262  // copy into regular field
263  copyExtendedGauge(*gauge, *gaugeEx, QUDA_CUDA_FIELD_LOCATION);
264 
265  // load the gauge field from gauge
266  gauge_param.gauge_order = (gauge_param.cuda_prec == QUDA_DOUBLE_PRECISION || gauge_param.reconstruct == QUDA_RECONSTRUCT_NO )
268  gauge_param.location = QUDA_CUDA_FIELD_LOCATION;
269 
270  loadGaugeQuda(gauge->Gauge_p(), &gauge_param);
271  double3 plaq = plaquette(*gaugeEx);
272  double charge = qChargeQuda();
273  printfQuda("Initial gauge field plaquette = %e topological charge = %e\n", plaq.x, charge);
274 
275  // Reunitarization setup
277  plaquette(*gaugeEx);
278 
279  // Do a warmup if requested
280  if (nwarm > 0) {
281  for (int step = 1; step <= nwarm; ++step) {
282  Monte( *gaugeEx, *randstates, beta_value, nhbsteps, novrsteps);
283  CallUnitarizeLinks(gaugeEx);
284  }
285  }
286 
287 
288  // copy into regular field
289  copyExtendedGauge(*gauge, *gaugeEx, QUDA_CUDA_FIELD_LOCATION);
290 
291  // load the gauge field from gauge
292  gauge_param.gauge_order = (gauge_param.cuda_prec == QUDA_DOUBLE_PRECISION || gauge_param.reconstruct == QUDA_RECONSTRUCT_NO )
294  gauge_param.location = QUDA_CUDA_FIELD_LOCATION;
295 
296  loadGaugeQuda(gauge->Gauge_p(), &gauge_param);
297  plaq = plaquette(*gaugeEx);
298  charge = qChargeQuda();
299  printfQuda("step=0 plaquette = %e topological charge = %e\n", plaq.x, charge);
300 
301 
302  freeGaugeQuda();
303 
304  for(int step=1; step<=nsteps; ++step){
305  printfQuda("Step %d\n", step);
306  Monte( *gaugeEx, *randstates, beta_value, nhbsteps, novrsteps);
307 
308  //Reunitarize gauge links...
309  CallUnitarizeLinks(gaugeEx);
310 
311  // copy into regular field
312  copyExtendedGauge(*gauge, *gaugeEx, QUDA_CUDA_FIELD_LOCATION);
313 
314  loadGaugeQuda(gauge->Gauge_p(), &gauge_param);
315  plaq = plaquette(*gaugeEx);
316  charge = qChargeQuda();
317  printfQuda("step=%d plaquette = %e topological charge = %e\n", step, plaq.x, charge);
318 
319  freeGaugeQuda();
320  }
321 
322  // Save if output string is specified
323  if (strcmp(gauge_outfile,"")) {
324 
325  printfQuda("Saving the gauge field to file %s\n", gauge_outfile);
326 
327  QudaGaugeParam gauge_param = newQudaGaugeParam();
328  setGaugeParam(gauge_param);
329 
330  size_t gSize = (gauge_param.cpu_prec == QUDA_DOUBLE_PRECISION) ? sizeof(double) : sizeof(float);
331  void *cpu_gauge[4];
332  for (int dir = 0; dir < 4; dir++) {
333  cpu_gauge[dir] = malloc(V*gaugeSiteSize*gSize);
334  }
335 
336  // copy into regular field
337  copyExtendedGauge(*gauge, *gaugeEx, QUDA_CUDA_FIELD_LOCATION);
338 
339  saveGaugeFieldQuda((void*)cpu_gauge, (void*)gauge, &gauge_param);
340 
341  write_gauge_field(gauge_outfile, cpu_gauge, gauge_param.cpu_prec, gauge_param.X, 0, (char**)0);
342 
343 
344  for (int dir = 0; dir<4; dir++) free(cpu_gauge[dir]);
345  } else {
346  printfQuda("No output file specified.\n");
347  }
348 
349  delete gauge;
350  delete gaugeEx;
351  //Release all temporary memory used for data exchange between GPUs in multi-GPU mode
353 
354  randstates->Release();
355  delete randstates;
356  }
357 
358  // stop the timer
359  time0 += clock();
360  time0 /= CLOCKS_PER_SEC;
361 
362  //printfQuda("\nDone: %i iter / %g secs = %g Gflops, total time = %g secs\n",
363  //inv_param.iter, inv_param.secs, inv_param.gflops/inv_param.secs, time0);
364  printfQuda("\nDone, total time = %g secs\n",
365  time0);
366 
367  freeGaugeQuda();
368 
369  // finalize the QUDA library
370  endQuda();
371 
372  // finalize the communications layer
373  finalizeComms();
374 
375  for (int dir = 0; dir<4; dir++) free(load_gauge[dir]);
376 
377  return 0;
378 }
static bool reunit_allow_svd
static size_t gSize
QudaTboundary t_boundary
Definition: gauge_field.h:20
int dimPartitioned(int dim)
Definition: test_util.cpp:1776
QudaReconstructType reconstruct_sloppy
Definition: quda.h:53
double anisotropy
Definition: quda.h:38
void Init()
Initialize CURAND RNG states.
Definition: random.cu:122
QudaGhostExchange ghostExchange
Definition: lattice_field.h:76
char gauge_outfile[]
Definition: test_util.cpp:1626
void endQuda(void)
void construct_gauge_field(void **gauge, int type, QudaPrecision precision, QudaGaugeParam *param)
Definition: test_util.cpp:1047
enum QudaPrecision_s QudaPrecision
int heatbath_num_heatbath_per_step
Definition: test_util.cpp:1768
int ga_pad
Definition: quda.h:63
int main(int argc, char **argv)
QudaGaugeFixed gauge_fix
Definition: quda.h:61
QudaLinkType type
Definition: quda.h:42
int device
Definition: test_util.cpp:1602
#define errorQuda(...)
Definition: util_quda.h:121
void setUnitarizeLinksConstants(double unitarize_eps, double max_error, bool allow_svd, bool svd_only, double svd_rel_error, double svd_abs_error)
QudaPrecision prec
Definition: test_util.cpp:1608
int * num_failures_dev
void loadGaugeQuda(void *h_gauge, QudaGaugeParam *param)
int process_command_line_option(int argc, char **argv, int *idx)
Definition: test_util.cpp:2019
static int R[4]
void finalizeComms()
Definition: test_util.cpp:128
QudaPrecision prec_sloppy
Definition: test_util.cpp:1609
QudaGaugeParam gauge_param
QudaGaugeFieldOrder gauge_order
Definition: quda.h:43
int gridsize_from_cmdline[]
Definition: test_util.cpp:49
QudaReconstructType link_recon_sloppy
Definition: test_util.cpp:1606
const char * get_prec_str(QudaPrecision prec)
Definition: misc.cpp:701
int ydim
Definition: test_util.cpp:1616
double anisotropy
Definition: test_util.cpp:1650
bool heatbath_coldstart
Definition: test_util.cpp:1770
int num_failures
void setDims(int *)
Definition: test_util.cpp:151
void display_test_info()
void freeGaugeQuda(void)
QudaPrecision & cuda_prec
static double svd_rel_error
int zdim
Definition: test_util.cpp:1617
int heatbath_warmup_steps
Definition: test_util.cpp:1766
void initQuda(int device)
void unitarizeLinks(cudaGaugeField &outfield, const cudaGaugeField &infield, int *fails)
QudaPrecision & cuda_prec_sloppy
void PGaugeExchangeFree()
Release all allocated memory used to exchange data between nodes.
void setTransferGPU(bool)
#define MAX(a, b)
void CallUnitarizeLinks(quda::cudaGaugeField *cudaInGauge)
void Release()
Release Device memory for CURAND RNG states.
Definition: random.cu:145
void setSpinorSiteSize(int n)
Definition: test_util.cpp:211
static bool reunit_svd_only
int Lsdim
Definition: test_util.cpp:1619
const char * get_recon_str(QudaReconstructType recon)
Definition: misc.cpp:768
QudaReconstructType link_recon
Definition: test_util.cpp:1605
Class declaration to initialize and hold CURAND RNG states.
Definition: random_quda.h:23
void saveGaugeFieldQuda(void *outGauge, void *inGauge, QudaGaugeParam *param)
QudaGaugeFieldOrder order
Definition: gauge_field.h:17
QudaPrecision cuda_prec_sloppy
Definition: quda.h:52
void InitGaugeField(cudaGaugeField &data)
Perform a cold start to the gauge field, identity SU(3) matrix, also fills the ghost links in multi-G...
static double svd_abs_error
int heatbath_num_steps
Definition: test_util.cpp:1767
QudaReconstructType reconstruct
Definition: quda.h:50
QudaPrecision cuda_prec
Definition: quda.h:49
int heatbath_num_overrelax_per_step
Definition: test_util.cpp:1769
int X[4]
Definition: quda.h:36
void usage(char **)
Definition: test_util.cpp:1783
int V
Definition: test_util.cpp:27
void setReunitarizationConsts()
char latfile[]
Definition: test_util.cpp:1623
QudaPrecision & cpu_prec
void copyExtendedResidentGaugeQuda(void *resident_gauge, QudaFieldLocation loc)
QudaFieldLocation location
Definition: quda.h:34
int xdim
Definition: test_util.cpp:1615
double tadpole_coeff
Definition: quda.h:39
GaugeFieldParam gParam
enum QudaReconstructType_s QudaReconstructType
Main header file for the QUDA library.
void initRand()
Definition: test_util.cpp:138
static double unitarize_eps
QudaLinkType link_type
Definition: gauge_field.h:19
double heatbath_beta_value
Definition: test_util.cpp:1765
#define printfQuda(...)
Definition: util_quda.h:115
QudaTboundary t_boundary
Definition: quda.h:45
double qChargeQuda()
#define device_malloc(size)
Definition: malloc_quda.h:64
void setGaugeParam(QudaGaugeParam &gauge_param)
QudaReconstructType reconstruct
Definition: gauge_field.h:16
QudaFieldCreate create
Definition: gauge_field.h:26
int tdim
Definition: test_util.cpp:1618
void Monte(cudaGaugeField &data, RNG &rngstate, double Beta, int nhb, int nover)
Perform heatbath and overrelaxation. Performs nhb heatbath steps followed by nover overrelaxation ste...
void initComms(int argc, char **argv, int *const commDims)
Definition: test_util.cpp:88
void read_gauge_field(const char *filename, void *gauge[], QudaPrecision prec, const int *X, int argc, char *argv[])
Definition: qio_field.h:14
cudaGaugeField * extendedGaugeResident
void copyExtendedGauge(GaugeField &out, const GaugeField &in, QudaFieldLocation location, void *Out=0, void *In=0)
double3 plaquette(const GaugeField &U)
Compute the plaquette of the gauge field.
Definition: gauge_plaq.cu:65
QudaPrecision cpu_prec
Definition: quda.h:47
int comm_dim_partitioned(int dim)
void write_gauge_field(const char *filename, void *gauge[], QudaPrecision prec, const int *X, int argc, char *argv[])
Definition: qio_field.h:19
#define gaugeSiteSize
Definition: face_gauge.cpp:34
QudaGaugeParam newQudaGaugeParam(void)
#define device_free(ptr)
Definition: malloc_quda.h:69