pyerrors.input.openQCD
1import os 2import fnmatch 3import struct 4import warnings 5import numpy as np # Thinly-wrapped numpy 6from ..obs import Obs 7from ..obs import CObs 8from ..correlators import Corr 9from .misc import fit_t0 10from .utils import sort_names 11 12 13def read_rwms(path, prefix, version='2.0', names=None, **kwargs): 14 """Read rwms format from given folder structure. Returns a list of length nrw 15 16 Parameters 17 ---------- 18 path : str 19 path that contains the data files 20 prefix : str 21 all files in path that start with prefix are considered as input files. 22 May be used together postfix to consider only special file endings. 23 Prefix is ignored, if the keyword 'files' is used. 24 version : str 25 version of openQCD, default 2.0 26 names : list 27 list of names that is assigned to the data according according 28 to the order in the file list. Use careful, if you do not provide file names! 29 r_start : list 30 list which contains the first config to be read for each replicum 31 r_stop : list 32 list which contains the last config to be read for each replicum 33 r_step : int 34 integer that defines a fixed step size between two measurements (in units of configs) 35 If not given, r_step=1 is assumed. 36 postfix : str 37 postfix of the file to read, e.g. '.ms1' for openQCD-files 38 files : list 39 list which contains the filenames to be read. No automatic detection of 40 files performed if given. 41 print_err : bool 42 Print additional information that is useful for debugging. 43 44 Returns 45 ------- 46 rwms : Obs 47 Reweighting factors read 48 """ 49 known_oqcd_versions = ['1.4', '1.6', '2.0'] 50 if version not in known_oqcd_versions: 51 raise Exception('Unknown openQCD version defined!') 52 print("Working with openQCD version " + version) 53 if 'postfix' in kwargs: 54 postfix = kwargs.get('postfix') 55 else: 56 postfix = '' 57 58 if 'files' in kwargs: 59 known_files = kwargs.get('files') 60 else: 61 known_files = [] 62 63 ls = _find_files(path, prefix, postfix, 'dat', known_files=known_files) 64 65 replica = len(ls) 66 67 if 'r_start' in kwargs: 68 r_start = kwargs.get('r_start') 69 if len(r_start) != replica: 70 raise Exception('r_start does not match number of replicas') 71 r_start = [o if o else None for o in r_start] 72 else: 73 r_start = [None] * replica 74 75 if 'r_stop' in kwargs: 76 r_stop = kwargs.get('r_stop') 77 if len(r_stop) != replica: 78 raise Exception('r_stop does not match number of replicas') 79 else: 80 r_stop = [None] * replica 81 82 if 'r_step' in kwargs: 83 r_step = kwargs.get('r_step') 84 else: 85 r_step = 1 86 87 print('Read reweighting factors from', prefix[:-1], ',', 88 replica, 'replica', end='') 89 90 if names is None: 91 rep_names = [] 92 for entry in ls: 93 truncated_entry = entry 94 suffixes = [".dat", ".rwms", ".ms1"] 95 for suffix in suffixes: 96 if truncated_entry.endswith(suffix): 97 truncated_entry = truncated_entry[0:-len(suffix)] 98 idx = truncated_entry.index('r') 99 rep_names.append(truncated_entry[:idx] + '|' + truncated_entry[idx:]) 100 else: 101 rep_names = names 102 103 rep_names = sort_names(rep_names) 104 105 print_err = 0 106 if 'print_err' in kwargs: 107 print_err = 1 108 print() 109 110 deltas = [] 111 112 configlist = [] 113 r_start_index = [] 114 r_stop_index = [] 115 116 for rep in range(replica): 117 tmp_array = [] 118 with open(path + '/' + ls[rep], 'rb') as fp: 119 120 t = fp.read(4) # number of reweighting factors 121 if rep == 0: 122 nrw = struct.unpack('i', t)[0] 123 if version == '2.0': 124 nrw = int(nrw / 2) 125 for k in range(nrw): 126 deltas.append([]) 127 else: 128 if ((nrw != struct.unpack('i', t)[0] and (not version == '2.0')) or (nrw != struct.unpack('i', t)[0] / 2 and version == '2.0')): 129 raise Exception('Error: different number of reweighting factors for replicum', rep) 130 131 for k in range(nrw): 132 tmp_array.append([]) 133 134 # This block is necessary for openQCD1.6 and openQCD2.0 ms1 files 135 nfct = [] 136 if version in ['1.6', '2.0']: 137 for i in range(nrw): 138 t = fp.read(4) 139 nfct.append(struct.unpack('i', t)[0]) 140 else: 141 for i in range(nrw): 142 nfct.append(1) 143 144 nsrc = [] 145 for i in range(nrw): 146 t = fp.read(4) 147 nsrc.append(struct.unpack('i', t)[0]) 148 if version == '2.0': 149 if not struct.unpack('i', fp.read(4))[0] == 0: 150 raise Exception("You are using the input for openQCD version 2.0, this is not correct.") 151 152 configlist.append([]) 153 while True: 154 t = fp.read(4) 155 if len(t) < 4: 156 break 157 config_no = struct.unpack('i', t)[0] 158 configlist[-1].append(config_no) 159 for i in range(nrw): 160 if (version == '2.0'): 161 tmpd = _read_array_openQCD2(fp) 162 tmpd = _read_array_openQCD2(fp) 163 tmp_rw = tmpd['arr'] 164 tmp_nfct = 1.0 165 for j in range(tmpd['n'][0]): 166 tmp_nfct *= np.mean(np.exp(-np.asarray(tmp_rw[j]))) 167 if print_err: 168 print(config_no, i, j, 169 np.mean(np.exp(-np.asarray(tmp_rw[j]))), 170 np.std(np.exp(-np.asarray(tmp_rw[j])))) 171 print('Sources:', 172 np.exp(-np.asarray(tmp_rw[j]))) 173 print('Partial factor:', tmp_nfct) 174 elif version == '1.6' or version == '1.4': 175 tmp_nfct = 1.0 176 for j in range(nfct[i]): 177 t = fp.read(8 * nsrc[i]) 178 t = fp.read(8 * nsrc[i]) 179 tmp_rw = struct.unpack('d' * nsrc[i], t) 180 tmp_nfct *= np.mean(np.exp(-np.asarray(tmp_rw))) 181 if print_err: 182 print(config_no, i, j, 183 np.mean(np.exp(-np.asarray(tmp_rw))), 184 np.std(np.exp(-np.asarray(tmp_rw)))) 185 print('Sources:', np.exp(-np.asarray(tmp_rw))) 186 print('Partial factor:', tmp_nfct) 187 tmp_array[i].append(tmp_nfct) 188 189 diffmeas = configlist[-1][-1] - configlist[-1][-2] 190 configlist[-1] = [item // diffmeas for item in configlist[-1]] 191 if configlist[-1][0] > 1 and diffmeas > 1: 192 warnings.warn('Assume thermalization and that the first measurement belongs to the first config.') 193 offset = configlist[-1][0] - 1 194 configlist[-1] = [item - offset for item in configlist[-1]] 195 196 if r_start[rep] is None: 197 r_start_index.append(0) 198 else: 199 try: 200 r_start_index.append(configlist[-1].index(r_start[rep])) 201 except ValueError: 202 raise Exception('Config %d not in file with range [%d, %d]' % ( 203 r_start[rep], configlist[-1][0], configlist[-1][-1])) from None 204 205 if r_stop[rep] is None: 206 r_stop_index.append(len(configlist[-1]) - 1) 207 else: 208 try: 209 r_stop_index.append(configlist[-1].index(r_stop[rep])) 210 except ValueError: 211 raise Exception('Config %d not in file with range [%d, %d]' % ( 212 r_stop[rep], configlist[-1][0], configlist[-1][-1])) from None 213 214 for k in range(nrw): 215 deltas[k].append(tmp_array[k][r_start_index[rep]:r_stop_index[rep] + 1][::r_step]) 216 217 if np.any([len(np.unique(np.diff(cl))) != 1 for cl in configlist]): 218 raise Exception('Irregular spaced data in input file!', [len(np.unique(np.diff(cl))) for cl in configlist]) 219 stepsizes = [list(np.unique(np.diff(cl)))[0] for cl in configlist] 220 if np.any([step != 1 for step in stepsizes]): 221 warnings.warn('Stepsize between configurations is greater than one!' + str(stepsizes), RuntimeWarning) 222 223 print(',', nrw, 'reweighting factors with', nsrc, 'sources') 224 result = [] 225 idl = [range(configlist[rep][r_start_index[rep]], configlist[rep][r_stop_index[rep]] + 1, r_step) for rep in range(replica)] 226 227 for t in range(nrw): 228 result.append(Obs(deltas[t], rep_names, idl=idl)) 229 return result 230 231 232def _extract_flowed_energy_density(path, prefix, dtr_read, xmin, spatial_extent, postfix='ms', **kwargs): 233 """Extract a dictionary with the flowed Yang-Mills action density from given .ms.dat files. 234 Returns a dictionary with Obs as values and flow times as keys. 235 236 It is assumed that all boundary effects have 237 sufficiently decayed at x0=xmin. 238 239 It is assumed that one measurement is performed for each config. 240 If this is not the case, the resulting idl, as well as the handling 241 of `r_start`, `r_stop` and `r_step` is wrong and the user has to correct 242 this in the resulting observable. 243 The function also assumes that `r_step` is the same across all replica. 244 245 Parameters 246 ---------- 247 path : str 248 Path to .ms.dat files 249 prefix : str 250 Ensemble prefix 251 dtr_read : int 252 Determines how many trajectories should be skipped 253 when reading the ms.dat files. 254 Corresponds to dtr_cnfg (dncnfg) in the openQCD input file. 255 xmin : int 256 First timeslice where the boundary 257 effects have sufficiently decayed. 258 spatial_extent : int 259 spatial extent of the lattice, required for normalization. 260 postfix : str 261 Postfix of measurement file (Default: ms) 262 r_start : list 263 list which contains the first config to be read for each replicum. 264 r_stop : list 265 list which contains the last config to be read for each replicum. 266 r_step : int 267 integer that defines a fixed step size between two measurements (in units of configs) 268 If not given, r_step=1 is assumed. 269 plaquette : bool 270 If true extract the plaquette estimate of t0 instead. 271 names : list 272 list of names that is assigned to the data according according 273 to the order in the file list. Use careful, if you do not provide file names! 274 files : list 275 list which contains the filenames to be read. No automatic detection of 276 files performed if given. 277 assume_thermalization : bool 278 If True: If the first record divided by the distance between two measurements is larger than 279 1, it is assumed that this is due to thermalization and the first measurement belongs 280 to the first config (default). 281 If False: The config numbers are assumed to be traj_number // difference 282 283 Returns 284 ------- 285 E_dict : dictionary 286 Dictionary with the flowed action density at flow times t 287 """ 288 289 if 'files' in kwargs: 290 known_files = kwargs.get('files') 291 else: 292 known_files = [] 293 294 ls = _find_files(path, prefix, postfix, 'dat', known_files=known_files) 295 296 replica = len(ls) 297 298 if 'r_start' in kwargs: 299 r_start = kwargs.get('r_start') 300 if len(r_start) != replica: 301 raise Exception('r_start does not match number of replicas') 302 r_start = [o if o else None for o in r_start] 303 else: 304 r_start = [None] * replica 305 306 if 'r_stop' in kwargs: 307 r_stop = kwargs.get('r_stop') 308 if len(r_stop) != replica: 309 raise Exception('r_stop does not match number of replicas') 310 else: 311 r_stop = [None] * replica 312 313 if 'r_step' in kwargs: 314 r_step = kwargs.get('r_step') 315 else: 316 r_step = 1 317 318 print('Extract flowed Yang-Mills action density from', prefix, ',', replica, 'replica') 319 320 if 'names' in kwargs: 321 rep_names = kwargs.get('names') 322 else: 323 rep_names = [] 324 for entry in ls: 325 truncated_entry = entry.split('.')[0] 326 idx = truncated_entry.index('r') 327 rep_names.append(truncated_entry[:idx] + '|' + truncated_entry[idx:]) 328 329 Ysum = [] 330 331 configlist = [] 332 r_start_index = [] 333 r_stop_index = [] 334 335 for rep in range(replica): 336 337 with open(path + '/' + ls[rep], 'rb') as fp: 338 t = fp.read(12) 339 header = struct.unpack('iii', t) 340 if rep == 0: 341 dn = header[0] 342 nn = header[1] 343 tmax = header[2] 344 elif dn != header[0] or nn != header[1] or tmax != header[2]: 345 raise Exception('Replica parameters do not match.') 346 347 t = fp.read(8) 348 if rep == 0: 349 eps = struct.unpack('d', t)[0] 350 print('Step size:', eps, ', Maximal t value:', dn * (nn) * eps) 351 elif eps != struct.unpack('d', t)[0]: 352 raise Exception('Values for eps do not match among replica.') 353 354 Ysl = [] 355 356 configlist.append([]) 357 while True: 358 t = fp.read(4) 359 if (len(t) < 4): 360 break 361 nc = struct.unpack('i', t)[0] 362 if nc % dtr_read == 0: 363 configlist[-1].append(nc) 364 t = fp.read(8 * tmax * (nn + 1)) 365 if kwargs.get('plaquette'): 366 if nc % dtr_read == 0: 367 Ysl.append(struct.unpack('d' * tmax * (nn + 1), t)) 368 t = fp.read(8 * tmax * (nn + 1)) 369 if not kwargs.get('plaquette'): 370 if nc % dtr_read == 0: 371 Ysl.append(struct.unpack('d' * tmax * (nn + 1), t)) 372 t = fp.read(8 * tmax * (nn + 1)) 373 374 Ysum.append([]) 375 for i, item in enumerate(Ysl): 376 Ysum[-1].append([np.mean(item[current + xmin: 377 current + tmax - xmin]) 378 for current in range(0, len(item), tmax)]) 379 380 diffmeas = configlist[-1][-1] - configlist[-1][-2] 381 if not all(c % diffmeas == 0 for c in configlist[-1]): 382 raise ValueError(f"Irregular spacing of configurations in {ls[rep]}, determined stepsize does not divide all trajectory steps.") 383 configlist[-1] = [item // diffmeas for item in configlist[-1]] 384 if kwargs.get('assume_thermalization', True) and configlist[-1][0] > 1: 385 warnings.warn('Assume thermalization and that the first measurement belongs to the first config.') 386 offset = configlist[-1][0] - 1 387 configlist[-1] = [item - offset for item in configlist[-1]] 388 389 if r_start[rep] is None: 390 r_start_index.append(0) 391 else: 392 try: 393 r_start_index.append(configlist[-1].index(r_start[rep])) 394 except ValueError: 395 raise Exception('Config %d not in file with range [%d, %d]' % ( 396 r_start[rep], configlist[-1][0], configlist[-1][-1])) from None 397 398 if r_stop[rep] is None: 399 r_stop_index.append(len(configlist[-1]) - 1) 400 else: 401 try: 402 r_stop_index.append(configlist[-1].index(r_stop[rep])) 403 except ValueError: 404 raise Exception('Config %d not in file with range [%d, %d]' % ( 405 r_stop[rep], configlist[-1][0], configlist[-1][-1])) from None 406 407 if np.any([len(np.unique(np.diff(cl))) != 1 for cl in configlist]): 408 raise Exception('Irregular spaced data in input file!', [len(np.unique(np.diff(cl))) for cl in configlist]) 409 stepsizes = [list(np.unique(np.diff(cl)))[0] for cl in configlist] 410 if np.any([step != 1 for step in stepsizes]): 411 warnings.warn('Stepsize between configurations is greater than one!' + str(stepsizes), RuntimeWarning) 412 413 idl = [range(configlist[rep][r_start_index[rep]], configlist[rep][r_stop_index[rep]] + 1, r_step) for rep in range(replica)] 414 E_dict = {} 415 for n in range(nn + 1): 416 samples = [] 417 for nrep, rep in enumerate(Ysum): 418 samples.append([]) 419 for cnfg in rep: 420 samples[-1].append(cnfg[n]) 421 samples[-1] = samples[-1][r_start_index[nrep]:r_stop_index[nrep] + 1][::r_step] 422 new_obs = Obs(samples, rep_names, idl=idl) 423 E_dict[n * dn * eps] = new_obs / (spatial_extent ** 3) 424 425 return E_dict 426 427 428def extract_t0(path, prefix, dtr_read, xmin, spatial_extent, fit_range=5, postfix='ms', c=0.3, **kwargs): 429 """Extract t0/a^2 from given .ms.dat files. Returns t0 as Obs. 430 431 It is assumed that all boundary effects have 432 sufficiently decayed at x0=xmin. 433 The data around the zero crossing of t^2<E> - c (where c=0.3 by default) 434 is fitted with a linear function 435 from which the exact root is extracted. 436 437 It is assumed that one measurement is performed for each config. 438 If this is not the case, the resulting idl, as well as the handling 439 of `r_start`, `r_stop` and `r_step` is wrong and the user has to correct 440 this in the resulting observable. 441 The function also assumes that `r_step` is the same across all replica. 442 443 Parameters 444 ---------- 445 path : str 446 Path to .ms.dat files 447 prefix : str 448 Ensemble prefix 449 dtr_read : int 450 Determines how many trajectories should be skipped 451 when reading the ms.dat files. 452 Corresponds to dtr_cnfg / dtr_ms in the openQCD input file. 453 xmin : int 454 First timeslice where the boundary 455 effects have sufficiently decayed. 456 spatial_extent : int 457 spatial extent of the lattice, required for normalization. 458 fit_range : int 459 Number of data points left and right of the zero 460 crossing to be included in the linear fit. (Default: 5) 461 postfix : str 462 Postfix of measurement file (Default: ms) 463 c: float 464 Constant that defines the flow scale. Default 0.3 for t_0, choose 2./3 for t_1. 465 r_start : list 466 list which contains the first config to be read for each replicum. 467 r_stop : list 468 list which contains the last config to be read for each replicum. 469 r_step : int 470 integer that defines a fixed step size between two measurements (in units of configs) 471 If not given, r_step=1 is assumed. 472 plaquette : bool 473 If true extract the plaquette estimate of t0 instead. 474 names : list 475 list of names that is assigned to the data according according 476 to the order in the file list. Use careful, if you do not provide file names! 477 files : list 478 list which contains the filenames to be read. No automatic detection of 479 files performed if given. 480 plot_fit : bool 481 If true, the fit for the extraction of t0 is shown together with the data. 482 assume_thermalization : bool 483 If True: If the first record divided by the distance between two measurements is larger than 484 1, it is assumed that this is due to thermalization and the first measurement belongs 485 to the first config (default). 486 If False: The config numbers are assumed to be traj_number // difference 487 488 Returns 489 ------- 490 t0 : Obs 491 Extracted t0 492 """ 493 494 E_dict = _extract_flowed_energy_density(path, prefix, dtr_read, xmin, spatial_extent, postfix, **kwargs) 495 t2E_dict = {} 496 for t in sorted(E_dict.keys()): 497 t2E_dict[t] = t ** 2 * E_dict[t] - c 498 499 return fit_t0(t2E_dict, fit_range, plot_fit=kwargs.get('plot_fit')) 500 501 502def extract_w0(path, prefix, dtr_read, xmin, spatial_extent, fit_range=5, postfix='ms', c=0.3, **kwargs): 503 """Extract w0/a from given .ms.dat files. Returns w0 as Obs. 504 505 It is assumed that all boundary effects have 506 sufficiently decayed at x0=xmin. 507 The data around the zero crossing of t d(t^2<E>)/dt - (where c=0.3 by default) 508 is fitted with a linear function 509 from which the exact root is extracted. 510 511 It is assumed that one measurement is performed for each config. 512 If this is not the case, the resulting idl, as well as the handling 513 of r_start, r_stop and r_step is wrong and the user has to correct 514 this in the resulting observable. 515 516 Parameters 517 ---------- 518 path : str 519 Path to .ms.dat files 520 prefix : str 521 Ensemble prefix 522 dtr_read : int 523 Determines how many trajectories should be skipped 524 when reading the ms.dat files. 525 Corresponds to dtr_cnfg / dtr_ms in the openQCD input file. 526 xmin : int 527 First timeslice where the boundary 528 effects have sufficiently decayed. 529 spatial_extent : int 530 spatial extent of the lattice, required for normalization. 531 fit_range : int 532 Number of data points left and right of the zero 533 crossing to be included in the linear fit. (Default: 5) 534 postfix : str 535 Postfix of measurement file (Default: ms) 536 c: float 537 Constant that defines the flow scale. Default 0.3 for w_0, choose 2./3 for w_1. 538 r_start : list 539 list which contains the first config to be read for each replicum. 540 r_stop : list 541 list which contains the last config to be read for each replicum. 542 r_step : int 543 integer that defines a fixed step size between two measurements (in units of configs) 544 If not given, r_step=1 is assumed. 545 plaquette : bool 546 If true extract the plaquette estimate of w0 instead. 547 names : list 548 list of names that is assigned to the data according according 549 to the order in the file list. Use careful, if you do not provide file names! 550 files : list 551 list which contains the filenames to be read. No automatic detection of 552 files performed if given. 553 plot_fit : bool 554 If true, the fit for the extraction of w0 is shown together with the data. 555 assume_thermalization : bool 556 If True: If the first record divided by the distance between two measurements is larger than 557 1, it is assumed that this is due to thermalization and the first measurement belongs 558 to the first config (default). 559 If False: The config numbers are assumed to be traj_number // difference 560 561 Returns 562 ------- 563 w0 : Obs 564 Extracted w0 565 """ 566 567 E_dict = _extract_flowed_energy_density(path, prefix, dtr_read, xmin, spatial_extent, postfix, **kwargs) 568 569 ftimes = sorted(E_dict.keys()) 570 571 t2E_dict = {} 572 for t in ftimes: 573 t2E_dict[t] = t ** 2 * E_dict[t] 574 575 tdtt2E_dict = {} 576 tdtt2E_dict[ftimes[0]] = ftimes[0] * (t2E_dict[ftimes[1]] - t2E_dict[ftimes[0]]) / (ftimes[1] - ftimes[0]) - c 577 for i in range(1, len(ftimes) - 1): 578 tdtt2E_dict[ftimes[i]] = ftimes[i] * (t2E_dict[ftimes[i + 1]] - t2E_dict[ftimes[i - 1]]) / (ftimes[i + 1] - ftimes[i - 1]) - c 579 tdtt2E_dict[ftimes[-1]] = ftimes[-1] * (t2E_dict[ftimes[-1]] - t2E_dict[ftimes[-2]]) / (ftimes[-1] - ftimes[-2]) - c 580 581 return np.sqrt(fit_t0(tdtt2E_dict, fit_range, plot_fit=kwargs.get('plot_fit'), observable='w0')) 582 583 584def _parse_array_openQCD2(d, n, size, wa, quadrupel=False): 585 arr = [] 586 if d == 2: 587 for i in range(n[0]): 588 tmp = wa[i * n[1]:(i + 1) * n[1]] 589 if quadrupel: 590 tmp2 = [] 591 for j in range(0, len(tmp), 2): 592 tmp2.append(tmp[j]) 593 arr.append(tmp2) 594 else: 595 arr.append(np.asarray(tmp)) 596 597 else: 598 raise Exception('Only two-dimensional arrays supported!') 599 600 return arr 601 602 603def _find_files(path, prefix, postfix, ext, known_files=[]): 604 found = [] 605 files = [] 606 607 if postfix != "": 608 if postfix[-1] != ".": 609 postfix = postfix + "." 610 if postfix[0] != ".": 611 postfix = "." + postfix 612 613 if ext[0] == ".": 614 ext = ext[1:] 615 616 pattern = prefix + "*" + postfix + ext 617 618 for (dirpath, dirnames, filenames) in os.walk(path + "/"): 619 found.extend(filenames) 620 break 621 622 if known_files != []: 623 for kf in known_files: 624 if kf not in found: 625 raise FileNotFoundError("Given file " + kf + " does not exist!") 626 627 return known_files 628 629 if not found: 630 raise FileNotFoundError(f"Error, directory '{path}' not found") 631 632 for f in found: 633 if fnmatch.fnmatch(f, pattern): 634 files.append(f) 635 636 if files == []: 637 raise Exception("No files found after pattern filter!") 638 639 files = sort_names(files) 640 return files 641 642 643def _read_array_openQCD2(fp): 644 t = fp.read(4) 645 d = struct.unpack('i', t)[0] 646 t = fp.read(4 * d) 647 n = struct.unpack('%di' % (d), t) 648 t = fp.read(4) 649 size = struct.unpack('i', t)[0] 650 if size == 4: 651 types = 'i' 652 elif size == 8: 653 types = 'd' 654 elif size == 16: 655 types = 'dd' 656 else: 657 raise Exception("Type for size '" + str(size) + "' not known.") 658 m = n[0] 659 for i in range(1, d): 660 m *= n[i] 661 662 t = fp.read(m * size) 663 tmp = struct.unpack('%d%s' % (m, types), t) 664 665 arr = _parse_array_openQCD2(d, n, size, tmp, quadrupel=True) 666 return {'d': d, 'n': n, 'size': size, 'arr': arr} 667 668 669def read_qtop(path, prefix, c, dtr_cnfg=1, version="openQCD", **kwargs): 670 """Read the topologial charge based on openQCD gradient flow measurements. 671 672 Parameters 673 ---------- 674 path : str 675 path of the measurement files 676 prefix : str 677 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat. 678 Ignored if file names are passed explicitly via keyword files. 679 c : double 680 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L. 681 dtr_cnfg : int 682 (optional) parameter that specifies the number of measurements 683 between two configs. 684 If it is not set, the distance between two measurements 685 in the file is assumed to be the distance between two configurations. 686 steps : int 687 (optional) Distance between two configurations in units of trajectories / 688 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 689 version : str 690 Either openQCD or sfqcd, depending on the data. 691 L : int 692 spatial length of the lattice in L/a. 693 HAS to be set if version != sfqcd, since openQCD does not provide 694 this in the header 695 r_start : list 696 list which contains the first config to be read for each replicum. 697 r_stop : list 698 list which contains the last config to be read for each replicum. 699 files : list 700 specify the exact files that need to be read 701 from path, practical if e.g. only one replicum is needed 702 postfix : str 703 postfix of the file to read, e.g. '.gfms.dat' for openQCD-files 704 names : list 705 Alternative labeling for replicas/ensembles. 706 Has to have the appropriate length. 707 Zeuthen_flow : bool 708 (optional) If True, the Zeuthen flow is used for Qtop. Only possible 709 for version=='sfqcd' If False, the Wilson flow is used. 710 integer_charge : bool 711 If True, the charge is rounded towards the nearest integer on each config. 712 713 Returns 714 ------- 715 result : Obs 716 Read topological charge 717 """ 718 719 return _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version=version, obspos=0, **kwargs) 720 721 722def read_gf_coupling(path, prefix, c, dtr_cnfg=1, Zeuthen_flow=True, **kwargs): 723 """Read the gradient flow coupling based on sfqcd gradient flow measurements. See 1607.06423 for details. 724 725 Note: The current implementation only works for c=0.3 and T=L. The definition of the coupling in 1607.06423 requires projection to topological charge zero which is not done within this function but has to be performed in a separate step. 726 727 Parameters 728 ---------- 729 path : str 730 path of the measurement files 731 prefix : str 732 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat. 733 Ignored if file names are passed explicitly via keyword files. 734 c : double 735 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L. 736 dtr_cnfg : int 737 (optional) parameter that specifies the number of measurements 738 between two configs. 739 If it is not set, the distance between two measurements 740 in the file is assumed to be the distance between two configurations. 741 steps : int 742 (optional) Distance between two configurations in units of trajectories / 743 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 744 r_start : list 745 list which contains the first config to be read for each replicum. 746 r_stop : list 747 list which contains the last config to be read for each replicum. 748 files : list 749 specify the exact files that need to be read 750 from path, practical if e.g. only one replicum is needed 751 names : list 752 Alternative labeling for replicas/ensembles. 753 Has to have the appropriate length. 754 postfix : str 755 postfix of the file to read, e.g. '.gfms.dat' for openQCD-files 756 Zeuthen_flow : bool 757 (optional) If True, the Zeuthen flow is used for the coupling. If False, the Wilson flow is used. 758 """ 759 760 if c != 0.3: 761 raise Exception("The required lattice norm is only implemented for c=0.3 at the moment.") 762 763 plaq = _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version="sfqcd", obspos=6, sum_t=False, Zeuthen_flow=Zeuthen_flow, integer_charge=False, **kwargs) 764 C2x1 = _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version="sfqcd", obspos=7, sum_t=False, Zeuthen_flow=Zeuthen_flow, integer_charge=False, **kwargs) 765 L = plaq.tag["L"] 766 T = plaq.tag["T"] 767 768 if T != L: 769 raise Exception("The required lattice norm is only implemented for T=L at the moment.") 770 771 if Zeuthen_flow is not True: 772 raise Exception("The required lattice norm is only implemented for the Zeuthen flow at the moment.") 773 774 t = (c * L) ** 2 / 8 775 776 normdict = {4: 0.012341170468270, 777 6: 0.010162691462430, 778 8: 0.009031614807931, 779 10: 0.008744966371393, 780 12: 0.008650917856809, 781 14: 8.611154391267955E-03, 782 16: 0.008591758449508, 783 20: 0.008575359627103, 784 24: 0.008569387847540, 785 28: 8.566803713382559E-03, 786 32: 0.008565541650006, 787 40: 8.564480684962046E-03, 788 48: 8.564098025073460E-03, 789 64: 8.563853943383087E-03} 790 791 return t * t * (5 / 3 * plaq - 1 / 12 * C2x1) / normdict[L] 792 793 794def _read_flow_obs(path, prefix, c, dtr_cnfg=1, version="openQCD", obspos=0, sum_t=True, **kwargs): 795 """Read a flow observable based on openQCD gradient flow measurements. 796 797 Parameters 798 ---------- 799 path : str 800 path of the measurement files 801 prefix : str 802 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat. 803 Ignored if file names are passed explicitly via keyword files. 804 c : double 805 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L. 806 dtr_cnfg : int 807 (optional) parameter that specifies the number of measurements 808 between two configs. 809 If it is not set, the distance between two measurements 810 in the file is assumed to be the distance between two configurations. 811 steps : int 812 (optional) Distance between two configurations in units of trajectories / 813 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 814 version : str 815 Either openQCD or sfqcd, depending on the data. 816 obspos : int 817 position of the obeservable in the measurement file. Only relevant for sfqcd files. 818 sum_t : bool 819 If true sum over all timeslices, if false only take the value at T/2. 820 L : int 821 spatial length of the lattice in L/a. 822 HAS to be set if version != sfqcd, since openQCD does not provide 823 this in the header 824 r_start : list 825 list which contains the first config to be read for each replicum. 826 r_stop : list 827 list which contains the last config to be read for each replicum. 828 files : list 829 specify the exact files that need to be read 830 from path, practical if e.g. only one replicum is needed 831 names : list 832 Alternative labeling for replicas/ensembles. 833 Has to have the appropriate length. 834 postfix : str 835 postfix of the file to read, e.g. '.gfms.dat' for openQCD-files 836 Zeuthen_flow : bool 837 (optional) If True, the Zeuthen flow is used for Qtop. Only possible 838 for version=='sfqcd' If False, the Wilson flow is used. 839 integer_charge : bool 840 If True, the charge is rounded towards the nearest integer on each config. 841 842 Returns 843 ------- 844 result : Obs 845 flow observable specified 846 """ 847 known_versions = ["openQCD", "sfqcd"] 848 849 if version not in known_versions: 850 raise Exception("Unknown openQCD version.") 851 if "steps" in kwargs: 852 steps = kwargs.get("steps") 853 if version == "sfqcd": 854 if "L" in kwargs: 855 supposed_L = kwargs.get("L") 856 else: 857 supposed_L = None 858 postfix = "gfms" 859 else: 860 if "L" not in kwargs: 861 raise Exception("This version of openQCD needs you to provide the spatial length of the lattice as parameter 'L'.") 862 else: 863 L = kwargs.get("L") 864 postfix = "ms" 865 866 if "postfix" in kwargs: 867 postfix = kwargs.get("postfix") 868 869 if "files" in kwargs: 870 known_files = kwargs.get("files") 871 else: 872 known_files = [] 873 874 files = _find_files(path, prefix, postfix, "dat", known_files=known_files) 875 876 if 'r_start' in kwargs: 877 r_start = kwargs.get('r_start') 878 if len(r_start) != len(files): 879 raise Exception('r_start does not match number of replicas') 880 r_start = [o if o else None for o in r_start] 881 else: 882 r_start = [None] * len(files) 883 884 if 'r_stop' in kwargs: 885 r_stop = kwargs.get('r_stop') 886 if len(r_stop) != len(files): 887 raise Exception('r_stop does not match number of replicas') 888 else: 889 r_stop = [None] * len(files) 890 rep_names = [] 891 892 zeuthen = kwargs.get('Zeuthen_flow', False) 893 if zeuthen and version not in ['sfqcd']: 894 raise Exception('Zeuthen flow can only be used for version==sfqcd') 895 896 r_start_index = [] 897 r_stop_index = [] 898 deltas = [] 899 configlist = [] 900 if not zeuthen: 901 obspos += 8 902 for rep, file in enumerate(files): 903 with open(path + "/" + file, "rb") as fp: 904 905 Q = [] 906 traj_list = [] 907 if version in ['sfqcd']: 908 t = fp.read(12) 909 header = struct.unpack('<iii', t) 910 zthfl = header[0] # Zeuthen flow -> if it's equal to 2 it means that the Zeuthen flow is also 'measured' (apart from the Wilson flow) 911 ncs = header[1] # number of different values for c in t_flow=1/8 c² L² -> measurements done for ncs c's 912 tmax = header[2] # lattice T/a 913 914 t = fp.read(12) 915 Ls = struct.unpack('<iii', t) 916 if (Ls[0] == Ls[1] and Ls[1] == Ls[2]): 917 L = Ls[0] 918 if not (supposed_L == L) and supposed_L: 919 raise Exception("It seems the length given in the header and by you contradict each other") 920 else: 921 raise Exception("Found more than one spatial length in header!") 922 923 t = fp.read(16) 924 header2 = struct.unpack('<dd', t) 925 tol = header2[0] 926 cmax = header2[1] # highest value of c used 927 928 if c > cmax: 929 raise Exception('Flow has been determined between c=0 and c=%lf with tolerance %lf' % (cmax, tol)) 930 931 if (zthfl == 2): 932 nfl = 2 # number of flows 933 else: 934 nfl = 1 935 iobs = 8 * nfl # number of flow observables calculated 936 937 while True: 938 t = fp.read(4) 939 if (len(t) < 4): 940 break 941 traj_list.append(struct.unpack('i', t)[0]) # trajectory number when measurement was done 942 943 for j in range(ncs + 1): 944 for i in range(iobs): 945 t = fp.read(8 * tmax) 946 if (i == obspos): # determines the flow observable -> i=0 <-> Zeuthen flow 947 Q.append(struct.unpack('d' * tmax, t)) 948 949 else: 950 t = fp.read(12) 951 header = struct.unpack('<iii', t) 952 # step size in integration steps "dnms" 953 dn = header[0] 954 # number of measurements, so "ntot"/dn 955 nn = header[1] 956 # lattice T/a 957 tmax = header[2] 958 959 t = fp.read(8) 960 eps = struct.unpack('d', t)[0] 961 962 while True: 963 t = fp.read(4) 964 if (len(t) < 4): 965 break 966 traj_list.append(struct.unpack('i', t)[0]) 967 # Wsl 968 t = fp.read(8 * tmax * (nn + 1)) 969 # Ysl 970 t = fp.read(8 * tmax * (nn + 1)) 971 # Qsl, which is asked for in this method 972 t = fp.read(8 * tmax * (nn + 1)) 973 # unpack the array of Qtops, 974 # on each timeslice t=0,...,tmax-1 and the 975 # measurement number in = 0...nn (see README.qcd1) 976 tmpd = struct.unpack('d' * tmax * (nn + 1), t) 977 Q.append(tmpd) 978 979 if len(np.unique(np.diff(traj_list))) != 1: 980 raise Exception("Irregularities in stepsize found") 981 else: 982 if 'steps' in kwargs: 983 if steps != traj_list[1] - traj_list[0]: 984 raise Exception("steps and the found stepsize are not the same") 985 else: 986 steps = traj_list[1] - traj_list[0] 987 988 configlist.append([tr // steps // dtr_cnfg for tr in traj_list]) 989 if configlist[-1][0] > 1: 990 offset = configlist[-1][0] - 1 991 warnings.warn('Assume thermalization and that the first measurement belongs to the first config. Offset = %d configs (%d trajectories / cycles)' % ( 992 offset, offset * steps)) 993 configlist[-1] = [item - offset for item in configlist[-1]] 994 995 if r_start[rep] is None: 996 r_start_index.append(0) 997 else: 998 try: 999 r_start_index.append(configlist[-1].index(r_start[rep])) 1000 except ValueError: 1001 raise Exception('Config %d not in file with range [%d, %d]' % ( 1002 r_start[rep], configlist[-1][0], configlist[-1][-1])) from None 1003 1004 if r_stop[rep] is None: 1005 r_stop_index.append(len(configlist[-1]) - 1) 1006 else: 1007 try: 1008 r_stop_index.append(configlist[-1].index(r_stop[rep])) 1009 except ValueError: 1010 raise Exception('Config %d not in file with range [%d, %d]' % ( 1011 r_stop[rep], configlist[-1][0], configlist[-1][-1])) from None 1012 1013 if version in ['sfqcd']: 1014 cstepsize = cmax / ncs 1015 index_aim = round(c / cstepsize) 1016 else: 1017 t_aim = (c * L) ** 2 / 8 1018 index_aim = round(t_aim / eps / dn) 1019 1020 Q_sum = [] 1021 for i, item in enumerate(Q): 1022 if sum_t is True: 1023 Q_sum.append([sum(item[current:current + tmax]) 1024 for current in range(0, len(item), tmax)]) 1025 else: 1026 Q_sum.append([item[int(tmax / 2)]]) 1027 Q_top = [] 1028 if version in ['sfqcd']: 1029 for i in range(len(Q_sum) // (ncs + 1)): 1030 Q_top.append(Q_sum[i * (ncs + 1) + index_aim][0]) 1031 else: 1032 for i in range(len(Q) // dtr_cnfg): 1033 Q_top.append(Q_sum[dtr_cnfg * i][index_aim]) 1034 if len(Q_top) != len(traj_list) // dtr_cnfg: 1035 raise Exception("qtops and traj_list dont have the same length") 1036 1037 if kwargs.get('integer_charge', False): 1038 Q_top = [round(q) for q in Q_top] 1039 1040 truncated_file = file[:-len(postfix)] 1041 1042 if "names" not in kwargs: 1043 try: 1044 idx = truncated_file.index('r') 1045 except Exception: 1046 if "names" not in kwargs: 1047 raise Exception("Automatic recognition of replicum failed, please enter the key word 'names'.") 1048 ens_name = truncated_file[:idx] 1049 rep_names.append(ens_name + '|' + truncated_file[idx:].split(".")[0]) 1050 else: 1051 names = kwargs.get("names") 1052 rep_names = names 1053 1054 deltas.append(Q_top) 1055 1056 rep_names = sort_names(rep_names) 1057 1058 idl = [range(int(configlist[rep][r_start_index[rep]]), int(configlist[rep][r_stop_index[rep]]) + 1, 1) for rep in range(len(deltas))] 1059 deltas = [deltas[nrep][r_start_index[nrep]:r_stop_index[nrep] + 1] for nrep in range(len(deltas))] 1060 result = Obs(deltas, rep_names, idl=idl) 1061 result.tag = {"T": tmax - 1, 1062 "L": L} 1063 return result 1064 1065 1066def qtop_projection(qtop, target=0): 1067 """Returns the projection to the topological charge sector defined by target. 1068 1069 Parameters 1070 ---------- 1071 path : Obs 1072 Topological charge. 1073 target : int 1074 Specifies the topological sector to be reweighted to (default 0) 1075 1076 Returns 1077 ------- 1078 reto : Obs 1079 projection to the topological charge sector defined by target 1080 """ 1081 if qtop.reweighted: 1082 raise Exception('You can not use a reweighted observable for reweighting!') 1083 1084 proj_qtop = [] 1085 for n in qtop.deltas: 1086 proj_qtop.append(np.array([1 if round(qtop.r_values[n] + q) == target else 0 for q in qtop.deltas[n]])) 1087 1088 reto = Obs(proj_qtop, qtop.names, idl=[qtop.idl[name] for name in qtop.names]) 1089 return reto 1090 1091 1092def read_qtop_sector(path, prefix, c, target=0, **kwargs): 1093 """Constructs reweighting factors to a specified topological sector. 1094 1095 Parameters 1096 ---------- 1097 path : str 1098 path of the measurement files 1099 prefix : str 1100 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat 1101 c : double 1102 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L 1103 target : int 1104 Specifies the topological sector to be reweighted to (default 0) 1105 dtr_cnfg : int 1106 (optional) parameter that specifies the number of trajectories 1107 between two configs. 1108 if it is not set, the distance between two measurements 1109 in the file is assumed to be the distance between two configurations. 1110 steps : int 1111 (optional) Distance between two configurations in units of trajectories / 1112 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 1113 version : str 1114 version string of the openQCD (sfqcd) version used to create 1115 the ensemble. Default is 2.0. May also be set to sfqcd. 1116 L : int 1117 spatial length of the lattice in L/a. 1118 HAS to be set if version != sfqcd, since openQCD does not provide 1119 this in the header 1120 r_start : list 1121 offset of the first ensemble, making it easier to match 1122 later on with other Obs 1123 r_stop : list 1124 last configurations that need to be read (per replicum) 1125 files : list 1126 specify the exact files that need to be read 1127 from path, practical if e.g. only one replicum is needed 1128 names : list 1129 Alternative labeling for replicas/ensembles. 1130 Has to have the appropriate length 1131 Zeuthen_flow : bool 1132 (optional) If True, the Zeuthen flow is used for Qtop. Only possible 1133 for version=='sfqcd' If False, the Wilson flow is used. 1134 1135 Returns 1136 ------- 1137 reto : Obs 1138 projection to the topological charge sector defined by target 1139 """ 1140 1141 if not isinstance(target, int): 1142 raise Exception("'target' has to be an integer.") 1143 1144 kwargs['integer_charge'] = True 1145 qtop = read_qtop(path, prefix, c, **kwargs) 1146 1147 return qtop_projection(qtop, target=target) 1148 1149 1150def read_ms5_xsf(path, prefix, qc, corr, sep="r", **kwargs): 1151 """ 1152 Read data from files in the specified directory with the specified prefix and quark combination extension, and return a `Corr` object containing the data. 1153 1154 Parameters 1155 ---------- 1156 path : str 1157 The directory to search for the files in. 1158 prefix : str 1159 The prefix to match the files against. 1160 qc : str 1161 The quark combination extension to match the files against. 1162 corr : str 1163 The correlator to extract data for. 1164 sep : str, optional 1165 The separator to use when parsing the replika names. 1166 **kwargs 1167 Additional keyword arguments. The following keyword arguments are recognized: 1168 1169 - names (List[str]): A list of names to use for the replicas. 1170 - files (List[str]): A list of files to read data from. 1171 - idl (List[List[int]]): A list of idls per replicum, resticting data to the idls given. 1172 1173 Returns 1174 ------- 1175 Corr 1176 A complex valued `Corr` object containing the data read from the files. In case of boudary to bulk correlators. 1177 or 1178 CObs 1179 A complex valued `CObs` object containing the data read from the files. In case of boudary to boundary correlators. 1180 1181 1182 Raises 1183 ------ 1184 FileNotFoundError 1185 If no files matching the specified prefix and quark combination extension are found in the specified directory. 1186 IOError 1187 If there is an error reading a file. 1188 struct.error 1189 If there is an error unpacking binary data. 1190 """ 1191 1192 # found = [] 1193 files = [] 1194 names = [] 1195 1196 # test if the input is correct 1197 if qc not in ['dd', 'ud', 'du', 'uu']: 1198 raise Exception("Unknown quark conbination!") 1199 1200 if corr not in ["gS", "gP", "gA", "gV", "gVt", "lA", "lV", "lVt", "lT", "lTt", "g1", "l1"]: 1201 raise Exception("Unknown correlator!") 1202 1203 if "files" in kwargs: 1204 known_files = kwargs.get("files") 1205 else: 1206 known_files = [] 1207 files = _find_files(path, prefix, "ms5_xsf_" + qc, "dat", known_files=known_files) 1208 1209 if "names" in kwargs: 1210 names = kwargs.get("names") 1211 else: 1212 for f in files: 1213 if not sep == "": 1214 se = f.split(".")[0] 1215 for s in f.split(".")[1:-2]: 1216 se += "." + s 1217 names.append(se.split(sep)[0] + "|r" + se.split(sep)[1]) 1218 else: 1219 names.append(prefix) 1220 if 'idl' in kwargs: 1221 expected_idl = kwargs.get('idl') 1222 names = sorted(names) 1223 files = sorted(files) 1224 1225 cnfgs = [] 1226 realsamples = [] 1227 imagsamples = [] 1228 repnum = 0 1229 for file in files: 1230 with open(path + "/" + file, "rb") as fp: 1231 1232 t = fp.read(8) 1233 kappa = struct.unpack('d', t)[0] 1234 t = fp.read(8) 1235 csw = struct.unpack('d', t)[0] 1236 t = fp.read(8) 1237 dF = struct.unpack('d', t)[0] 1238 t = fp.read(8) 1239 zF = struct.unpack('d', t)[0] 1240 1241 t = fp.read(4) 1242 tmax = struct.unpack('i', t)[0] 1243 t = fp.read(4) 1244 bnd = struct.unpack('i', t)[0] 1245 1246 placesBI = ["gS", "gP", 1247 "gA", "gV", 1248 "gVt", "lA", 1249 "lV", "lVt", 1250 "lT", "lTt"] 1251 placesBB = ["g1", "l1"] 1252 1253 # the chunks have the following structure: 1254 # confignumber, 10x timedependent complex correlators as doubles, 2x timeindependent complex correlators as doubles 1255 1256 chunksize = 4 + (8 * 2 * tmax * 10) + (8 * 2 * 2) 1257 packstr = '=i' + ('d' * 2 * tmax * 10) + ('d' * 2 * 2) 1258 cnfgs.append([]) 1259 realsamples.append([]) 1260 imagsamples.append([]) 1261 for t in range(tmax): 1262 realsamples[repnum].append([]) 1263 imagsamples[repnum].append([]) 1264 if 'idl' in kwargs: 1265 left_idl = set(expected_idl[repnum]) 1266 while True: 1267 cnfgt = fp.read(chunksize) 1268 if not cnfgt: 1269 break 1270 asascii = struct.unpack(packstr, cnfgt) 1271 cnfg = asascii[0] 1272 idl_wanted = True 1273 if 'idl' in kwargs: 1274 idl_wanted = (cnfg in expected_idl[repnum]) 1275 left_idl = left_idl - set([cnfg]) 1276 if idl_wanted: 1277 cnfgs[repnum].append(cnfg) 1278 1279 if corr not in placesBB: 1280 tmpcorr = asascii[1 + 2 * tmax * placesBI.index(corr):1 + 2 * tmax * placesBI.index(corr) + 2 * tmax] 1281 else: 1282 tmpcorr = asascii[1 + 2 * tmax * len(placesBI) + 2 * placesBB.index(corr):1 + 2 * tmax * len(placesBI) + 2 * placesBB.index(corr) + 2] 1283 1284 corrres = [[], []] 1285 for i in range(len(tmpcorr)): 1286 corrres[i % 2].append(tmpcorr[i]) 1287 for t in range(int(len(tmpcorr) / 2)): 1288 realsamples[repnum][t].append(corrres[0][t]) 1289 for t in range(int(len(tmpcorr) / 2)): 1290 imagsamples[repnum][t].append(corrres[1][t]) 1291 if 'idl' in kwargs: 1292 left_idl = list(left_idl) 1293 if expected_idl[repnum] == left_idl: 1294 raise ValueError("None of the idls searched for were found in replikum of file " + file) 1295 elif len(left_idl) > 0: 1296 warnings.warn('Could not find idls ' + str(left_idl) + ' in replikum of file ' + file, UserWarning) 1297 repnum += 1 1298 s = "Read correlator " + corr + " from " + str(repnum) + " replika with idls" + str(realsamples[0][t]) 1299 for rep in range(1, repnum): 1300 s += ", " + str(realsamples[rep][t]) 1301 print(s) 1302 print("Asserted run parameters:\n T:", tmax, "kappa:", kappa, "csw:", csw, "dF:", dF, "zF:", zF, "bnd:", bnd) 1303 1304 # we have the data now... but we need to re format the whole thing and put it into Corr objects. 1305 1306 compObs = [] 1307 1308 for t in range(int(len(tmpcorr) / 2)): 1309 compObs.append(CObs(Obs([realsamples[rep][t] for rep in range(repnum)], names=names, idl=cnfgs), 1310 Obs([imagsamples[rep][t] for rep in range(repnum)], names=names, idl=cnfgs))) 1311 1312 if len(compObs) == 1: 1313 return compObs[0] 1314 else: 1315 return Corr(compObs)
14def read_rwms(path, prefix, version='2.0', names=None, **kwargs): 15 """Read rwms format from given folder structure. Returns a list of length nrw 16 17 Parameters 18 ---------- 19 path : str 20 path that contains the data files 21 prefix : str 22 all files in path that start with prefix are considered as input files. 23 May be used together postfix to consider only special file endings. 24 Prefix is ignored, if the keyword 'files' is used. 25 version : str 26 version of openQCD, default 2.0 27 names : list 28 list of names that is assigned to the data according according 29 to the order in the file list. Use careful, if you do not provide file names! 30 r_start : list 31 list which contains the first config to be read for each replicum 32 r_stop : list 33 list which contains the last config to be read for each replicum 34 r_step : int 35 integer that defines a fixed step size between two measurements (in units of configs) 36 If not given, r_step=1 is assumed. 37 postfix : str 38 postfix of the file to read, e.g. '.ms1' for openQCD-files 39 files : list 40 list which contains the filenames to be read. No automatic detection of 41 files performed if given. 42 print_err : bool 43 Print additional information that is useful for debugging. 44 45 Returns 46 ------- 47 rwms : Obs 48 Reweighting factors read 49 """ 50 known_oqcd_versions = ['1.4', '1.6', '2.0'] 51 if version not in known_oqcd_versions: 52 raise Exception('Unknown openQCD version defined!') 53 print("Working with openQCD version " + version) 54 if 'postfix' in kwargs: 55 postfix = kwargs.get('postfix') 56 else: 57 postfix = '' 58 59 if 'files' in kwargs: 60 known_files = kwargs.get('files') 61 else: 62 known_files = [] 63 64 ls = _find_files(path, prefix, postfix, 'dat', known_files=known_files) 65 66 replica = len(ls) 67 68 if 'r_start' in kwargs: 69 r_start = kwargs.get('r_start') 70 if len(r_start) != replica: 71 raise Exception('r_start does not match number of replicas') 72 r_start = [o if o else None for o in r_start] 73 else: 74 r_start = [None] * replica 75 76 if 'r_stop' in kwargs: 77 r_stop = kwargs.get('r_stop') 78 if len(r_stop) != replica: 79 raise Exception('r_stop does not match number of replicas') 80 else: 81 r_stop = [None] * replica 82 83 if 'r_step' in kwargs: 84 r_step = kwargs.get('r_step') 85 else: 86 r_step = 1 87 88 print('Read reweighting factors from', prefix[:-1], ',', 89 replica, 'replica', end='') 90 91 if names is None: 92 rep_names = [] 93 for entry in ls: 94 truncated_entry = entry 95 suffixes = [".dat", ".rwms", ".ms1"] 96 for suffix in suffixes: 97 if truncated_entry.endswith(suffix): 98 truncated_entry = truncated_entry[0:-len(suffix)] 99 idx = truncated_entry.index('r') 100 rep_names.append(truncated_entry[:idx] + '|' + truncated_entry[idx:]) 101 else: 102 rep_names = names 103 104 rep_names = sort_names(rep_names) 105 106 print_err = 0 107 if 'print_err' in kwargs: 108 print_err = 1 109 print() 110 111 deltas = [] 112 113 configlist = [] 114 r_start_index = [] 115 r_stop_index = [] 116 117 for rep in range(replica): 118 tmp_array = [] 119 with open(path + '/' + ls[rep], 'rb') as fp: 120 121 t = fp.read(4) # number of reweighting factors 122 if rep == 0: 123 nrw = struct.unpack('i', t)[0] 124 if version == '2.0': 125 nrw = int(nrw / 2) 126 for k in range(nrw): 127 deltas.append([]) 128 else: 129 if ((nrw != struct.unpack('i', t)[0] and (not version == '2.0')) or (nrw != struct.unpack('i', t)[0] / 2 and version == '2.0')): 130 raise Exception('Error: different number of reweighting factors for replicum', rep) 131 132 for k in range(nrw): 133 tmp_array.append([]) 134 135 # This block is necessary for openQCD1.6 and openQCD2.0 ms1 files 136 nfct = [] 137 if version in ['1.6', '2.0']: 138 for i in range(nrw): 139 t = fp.read(4) 140 nfct.append(struct.unpack('i', t)[0]) 141 else: 142 for i in range(nrw): 143 nfct.append(1) 144 145 nsrc = [] 146 for i in range(nrw): 147 t = fp.read(4) 148 nsrc.append(struct.unpack('i', t)[0]) 149 if version == '2.0': 150 if not struct.unpack('i', fp.read(4))[0] == 0: 151 raise Exception("You are using the input for openQCD version 2.0, this is not correct.") 152 153 configlist.append([]) 154 while True: 155 t = fp.read(4) 156 if len(t) < 4: 157 break 158 config_no = struct.unpack('i', t)[0] 159 configlist[-1].append(config_no) 160 for i in range(nrw): 161 if (version == '2.0'): 162 tmpd = _read_array_openQCD2(fp) 163 tmpd = _read_array_openQCD2(fp) 164 tmp_rw = tmpd['arr'] 165 tmp_nfct = 1.0 166 for j in range(tmpd['n'][0]): 167 tmp_nfct *= np.mean(np.exp(-np.asarray(tmp_rw[j]))) 168 if print_err: 169 print(config_no, i, j, 170 np.mean(np.exp(-np.asarray(tmp_rw[j]))), 171 np.std(np.exp(-np.asarray(tmp_rw[j])))) 172 print('Sources:', 173 np.exp(-np.asarray(tmp_rw[j]))) 174 print('Partial factor:', tmp_nfct) 175 elif version == '1.6' or version == '1.4': 176 tmp_nfct = 1.0 177 for j in range(nfct[i]): 178 t = fp.read(8 * nsrc[i]) 179 t = fp.read(8 * nsrc[i]) 180 tmp_rw = struct.unpack('d' * nsrc[i], t) 181 tmp_nfct *= np.mean(np.exp(-np.asarray(tmp_rw))) 182 if print_err: 183 print(config_no, i, j, 184 np.mean(np.exp(-np.asarray(tmp_rw))), 185 np.std(np.exp(-np.asarray(tmp_rw)))) 186 print('Sources:', np.exp(-np.asarray(tmp_rw))) 187 print('Partial factor:', tmp_nfct) 188 tmp_array[i].append(tmp_nfct) 189 190 diffmeas = configlist[-1][-1] - configlist[-1][-2] 191 configlist[-1] = [item // diffmeas for item in configlist[-1]] 192 if configlist[-1][0] > 1 and diffmeas > 1: 193 warnings.warn('Assume thermalization and that the first measurement belongs to the first config.') 194 offset = configlist[-1][0] - 1 195 configlist[-1] = [item - offset for item in configlist[-1]] 196 197 if r_start[rep] is None: 198 r_start_index.append(0) 199 else: 200 try: 201 r_start_index.append(configlist[-1].index(r_start[rep])) 202 except ValueError: 203 raise Exception('Config %d not in file with range [%d, %d]' % ( 204 r_start[rep], configlist[-1][0], configlist[-1][-1])) from None 205 206 if r_stop[rep] is None: 207 r_stop_index.append(len(configlist[-1]) - 1) 208 else: 209 try: 210 r_stop_index.append(configlist[-1].index(r_stop[rep])) 211 except ValueError: 212 raise Exception('Config %d not in file with range [%d, %d]' % ( 213 r_stop[rep], configlist[-1][0], configlist[-1][-1])) from None 214 215 for k in range(nrw): 216 deltas[k].append(tmp_array[k][r_start_index[rep]:r_stop_index[rep] + 1][::r_step]) 217 218 if np.any([len(np.unique(np.diff(cl))) != 1 for cl in configlist]): 219 raise Exception('Irregular spaced data in input file!', [len(np.unique(np.diff(cl))) for cl in configlist]) 220 stepsizes = [list(np.unique(np.diff(cl)))[0] for cl in configlist] 221 if np.any([step != 1 for step in stepsizes]): 222 warnings.warn('Stepsize between configurations is greater than one!' + str(stepsizes), RuntimeWarning) 223 224 print(',', nrw, 'reweighting factors with', nsrc, 'sources') 225 result = [] 226 idl = [range(configlist[rep][r_start_index[rep]], configlist[rep][r_stop_index[rep]] + 1, r_step) for rep in range(replica)] 227 228 for t in range(nrw): 229 result.append(Obs(deltas[t], rep_names, idl=idl)) 230 return result
Read rwms format from given folder structure. Returns a list of length nrw
Parameters
- path (str): path that contains the data files
- prefix (str): all files in path that start with prefix are considered as input files. May be used together postfix to consider only special file endings. Prefix is ignored, if the keyword 'files' is used.
- version (str): version of openQCD, default 2.0
- names (list): list of names that is assigned to the data according according to the order in the file list. Use careful, if you do not provide file names!
- r_start (list): list which contains the first config to be read for each replicum
- r_stop (list): list which contains the last config to be read for each replicum
- r_step (int): integer that defines a fixed step size between two measurements (in units of configs) If not given, r_step=1 is assumed.
- postfix (str): postfix of the file to read, e.g. '.ms1' for openQCD-files
- files (list): list which contains the filenames to be read. No automatic detection of files performed if given.
- print_err (bool): Print additional information that is useful for debugging.
Returns
- rwms (Obs): Reweighting factors read
429def extract_t0(path, prefix, dtr_read, xmin, spatial_extent, fit_range=5, postfix='ms', c=0.3, **kwargs): 430 """Extract t0/a^2 from given .ms.dat files. Returns t0 as Obs. 431 432 It is assumed that all boundary effects have 433 sufficiently decayed at x0=xmin. 434 The data around the zero crossing of t^2<E> - c (where c=0.3 by default) 435 is fitted with a linear function 436 from which the exact root is extracted. 437 438 It is assumed that one measurement is performed for each config. 439 If this is not the case, the resulting idl, as well as the handling 440 of `r_start`, `r_stop` and `r_step` is wrong and the user has to correct 441 this in the resulting observable. 442 The function also assumes that `r_step` is the same across all replica. 443 444 Parameters 445 ---------- 446 path : str 447 Path to .ms.dat files 448 prefix : str 449 Ensemble prefix 450 dtr_read : int 451 Determines how many trajectories should be skipped 452 when reading the ms.dat files. 453 Corresponds to dtr_cnfg / dtr_ms in the openQCD input file. 454 xmin : int 455 First timeslice where the boundary 456 effects have sufficiently decayed. 457 spatial_extent : int 458 spatial extent of the lattice, required for normalization. 459 fit_range : int 460 Number of data points left and right of the zero 461 crossing to be included in the linear fit. (Default: 5) 462 postfix : str 463 Postfix of measurement file (Default: ms) 464 c: float 465 Constant that defines the flow scale. Default 0.3 for t_0, choose 2./3 for t_1. 466 r_start : list 467 list which contains the first config to be read for each replicum. 468 r_stop : list 469 list which contains the last config to be read for each replicum. 470 r_step : int 471 integer that defines a fixed step size between two measurements (in units of configs) 472 If not given, r_step=1 is assumed. 473 plaquette : bool 474 If true extract the plaquette estimate of t0 instead. 475 names : list 476 list of names that is assigned to the data according according 477 to the order in the file list. Use careful, if you do not provide file names! 478 files : list 479 list which contains the filenames to be read. No automatic detection of 480 files performed if given. 481 plot_fit : bool 482 If true, the fit for the extraction of t0 is shown together with the data. 483 assume_thermalization : bool 484 If True: If the first record divided by the distance between two measurements is larger than 485 1, it is assumed that this is due to thermalization and the first measurement belongs 486 to the first config (default). 487 If False: The config numbers are assumed to be traj_number // difference 488 489 Returns 490 ------- 491 t0 : Obs 492 Extracted t0 493 """ 494 495 E_dict = _extract_flowed_energy_density(path, prefix, dtr_read, xmin, spatial_extent, postfix, **kwargs) 496 t2E_dict = {} 497 for t in sorted(E_dict.keys()): 498 t2E_dict[t] = t ** 2 * E_dict[t] - c 499 500 return fit_t0(t2E_dict, fit_range, plot_fit=kwargs.get('plot_fit'))
Extract t0/a^2 from given .ms.dat files. Returns t0 as Obs.
It is assumed that all boundary effects have
sufficiently decayed at x0=xmin.
The data around the zero crossing of t^2
It is assumed that one measurement is performed for each config.
If this is not the case, the resulting idl, as well as the handling
of r_start, r_stop and r_step is wrong and the user has to correct
this in the resulting observable.
The function also assumes that r_step is the same across all replica.
Parameters
- path (str): Path to .ms.dat files
- prefix (str): Ensemble prefix
- dtr_read (int): Determines how many trajectories should be skipped when reading the ms.dat files. Corresponds to dtr_cnfg / dtr_ms in the openQCD input file.
- xmin (int): First timeslice where the boundary effects have sufficiently decayed.
- spatial_extent (int): spatial extent of the lattice, required for normalization.
- fit_range (int): Number of data points left and right of the zero crossing to be included in the linear fit. (Default: 5)
- postfix (str): Postfix of measurement file (Default: ms)
- c (float): Constant that defines the flow scale. Default 0.3 for t_0, choose 2./3 for t_1.
- r_start (list): list which contains the first config to be read for each replicum.
- r_stop (list): list which contains the last config to be read for each replicum.
- r_step (int): integer that defines a fixed step size between two measurements (in units of configs) If not given, r_step=1 is assumed.
- plaquette (bool): If true extract the plaquette estimate of t0 instead.
- names (list): list of names that is assigned to the data according according to the order in the file list. Use careful, if you do not provide file names!
- files (list): list which contains the filenames to be read. No automatic detection of files performed if given.
- plot_fit (bool): If true, the fit for the extraction of t0 is shown together with the data.
- assume_thermalization (bool): If True: If the first record divided by the distance between two measurements is larger than 1, it is assumed that this is due to thermalization and the first measurement belongs to the first config (default). If False: The config numbers are assumed to be traj_number // difference
Returns
- t0 (Obs): Extracted t0
503def extract_w0(path, prefix, dtr_read, xmin, spatial_extent, fit_range=5, postfix='ms', c=0.3, **kwargs): 504 """Extract w0/a from given .ms.dat files. Returns w0 as Obs. 505 506 It is assumed that all boundary effects have 507 sufficiently decayed at x0=xmin. 508 The data around the zero crossing of t d(t^2<E>)/dt - (where c=0.3 by default) 509 is fitted with a linear function 510 from which the exact root is extracted. 511 512 It is assumed that one measurement is performed for each config. 513 If this is not the case, the resulting idl, as well as the handling 514 of r_start, r_stop and r_step is wrong and the user has to correct 515 this in the resulting observable. 516 517 Parameters 518 ---------- 519 path : str 520 Path to .ms.dat files 521 prefix : str 522 Ensemble prefix 523 dtr_read : int 524 Determines how many trajectories should be skipped 525 when reading the ms.dat files. 526 Corresponds to dtr_cnfg / dtr_ms in the openQCD input file. 527 xmin : int 528 First timeslice where the boundary 529 effects have sufficiently decayed. 530 spatial_extent : int 531 spatial extent of the lattice, required for normalization. 532 fit_range : int 533 Number of data points left and right of the zero 534 crossing to be included in the linear fit. (Default: 5) 535 postfix : str 536 Postfix of measurement file (Default: ms) 537 c: float 538 Constant that defines the flow scale. Default 0.3 for w_0, choose 2./3 for w_1. 539 r_start : list 540 list which contains the first config to be read for each replicum. 541 r_stop : list 542 list which contains the last config to be read for each replicum. 543 r_step : int 544 integer that defines a fixed step size between two measurements (in units of configs) 545 If not given, r_step=1 is assumed. 546 plaquette : bool 547 If true extract the plaquette estimate of w0 instead. 548 names : list 549 list of names that is assigned to the data according according 550 to the order in the file list. Use careful, if you do not provide file names! 551 files : list 552 list which contains the filenames to be read. No automatic detection of 553 files performed if given. 554 plot_fit : bool 555 If true, the fit for the extraction of w0 is shown together with the data. 556 assume_thermalization : bool 557 If True: If the first record divided by the distance between two measurements is larger than 558 1, it is assumed that this is due to thermalization and the first measurement belongs 559 to the first config (default). 560 If False: The config numbers are assumed to be traj_number // difference 561 562 Returns 563 ------- 564 w0 : Obs 565 Extracted w0 566 """ 567 568 E_dict = _extract_flowed_energy_density(path, prefix, dtr_read, xmin, spatial_extent, postfix, **kwargs) 569 570 ftimes = sorted(E_dict.keys()) 571 572 t2E_dict = {} 573 for t in ftimes: 574 t2E_dict[t] = t ** 2 * E_dict[t] 575 576 tdtt2E_dict = {} 577 tdtt2E_dict[ftimes[0]] = ftimes[0] * (t2E_dict[ftimes[1]] - t2E_dict[ftimes[0]]) / (ftimes[1] - ftimes[0]) - c 578 for i in range(1, len(ftimes) - 1): 579 tdtt2E_dict[ftimes[i]] = ftimes[i] * (t2E_dict[ftimes[i + 1]] - t2E_dict[ftimes[i - 1]]) / (ftimes[i + 1] - ftimes[i - 1]) - c 580 tdtt2E_dict[ftimes[-1]] = ftimes[-1] * (t2E_dict[ftimes[-1]] - t2E_dict[ftimes[-2]]) / (ftimes[-1] - ftimes[-2]) - c 581 582 return np.sqrt(fit_t0(tdtt2E_dict, fit_range, plot_fit=kwargs.get('plot_fit'), observable='w0'))
Extract w0/a from given .ms.dat files. Returns w0 as Obs.
It is assumed that all boundary effects have
sufficiently decayed at x0=xmin.
The data around the zero crossing of t d(t^2
It is assumed that one measurement is performed for each config. If this is not the case, the resulting idl, as well as the handling of r_start, r_stop and r_step is wrong and the user has to correct this in the resulting observable.
Parameters
- path (str): Path to .ms.dat files
- prefix (str): Ensemble prefix
- dtr_read (int): Determines how many trajectories should be skipped when reading the ms.dat files. Corresponds to dtr_cnfg / dtr_ms in the openQCD input file.
- xmin (int): First timeslice where the boundary effects have sufficiently decayed.
- spatial_extent (int): spatial extent of the lattice, required for normalization.
- fit_range (int): Number of data points left and right of the zero crossing to be included in the linear fit. (Default: 5)
- postfix (str): Postfix of measurement file (Default: ms)
- c (float): Constant that defines the flow scale. Default 0.3 for w_0, choose 2./3 for w_1.
- r_start (list): list which contains the first config to be read for each replicum.
- r_stop (list): list which contains the last config to be read for each replicum.
- r_step (int): integer that defines a fixed step size between two measurements (in units of configs) If not given, r_step=1 is assumed.
- plaquette (bool): If true extract the plaquette estimate of w0 instead.
- names (list): list of names that is assigned to the data according according to the order in the file list. Use careful, if you do not provide file names!
- files (list): list which contains the filenames to be read. No automatic detection of files performed if given.
- plot_fit (bool): If true, the fit for the extraction of w0 is shown together with the data.
- assume_thermalization (bool): If True: If the first record divided by the distance between two measurements is larger than 1, it is assumed that this is due to thermalization and the first measurement belongs to the first config (default). If False: The config numbers are assumed to be traj_number // difference
Returns
- w0 (Obs): Extracted w0
670def read_qtop(path, prefix, c, dtr_cnfg=1, version="openQCD", **kwargs): 671 """Read the topologial charge based on openQCD gradient flow measurements. 672 673 Parameters 674 ---------- 675 path : str 676 path of the measurement files 677 prefix : str 678 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat. 679 Ignored if file names are passed explicitly via keyword files. 680 c : double 681 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L. 682 dtr_cnfg : int 683 (optional) parameter that specifies the number of measurements 684 between two configs. 685 If it is not set, the distance between two measurements 686 in the file is assumed to be the distance between two configurations. 687 steps : int 688 (optional) Distance between two configurations in units of trajectories / 689 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 690 version : str 691 Either openQCD or sfqcd, depending on the data. 692 L : int 693 spatial length of the lattice in L/a. 694 HAS to be set if version != sfqcd, since openQCD does not provide 695 this in the header 696 r_start : list 697 list which contains the first config to be read for each replicum. 698 r_stop : list 699 list which contains the last config to be read for each replicum. 700 files : list 701 specify the exact files that need to be read 702 from path, practical if e.g. only one replicum is needed 703 postfix : str 704 postfix of the file to read, e.g. '.gfms.dat' for openQCD-files 705 names : list 706 Alternative labeling for replicas/ensembles. 707 Has to have the appropriate length. 708 Zeuthen_flow : bool 709 (optional) If True, the Zeuthen flow is used for Qtop. Only possible 710 for version=='sfqcd' If False, the Wilson flow is used. 711 integer_charge : bool 712 If True, the charge is rounded towards the nearest integer on each config. 713 714 Returns 715 ------- 716 result : Obs 717 Read topological charge 718 """ 719 720 return _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version=version, obspos=0, **kwargs)
Read the topologial charge based on openQCD gradient flow measurements.
Parameters
- path (str): path of the measurement files
- prefix (str):
prefix of the measurement files, e.g.
_id0_r0.ms.dat. Ignored if file names are passed explicitly via keyword files. - c (double): Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L.
- dtr_cnfg (int): (optional) parameter that specifies the number of measurements between two configs. If it is not set, the distance between two measurements in the file is assumed to be the distance between two configurations.
- steps (int): (optional) Distance between two configurations in units of trajectories / cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given
- version (str): Either openQCD or sfqcd, depending on the data.
- L (int): spatial length of the lattice in L/a. HAS to be set if version != sfqcd, since openQCD does not provide this in the header
- r_start (list): list which contains the first config to be read for each replicum.
- r_stop (list): list which contains the last config to be read for each replicum.
- files (list): specify the exact files that need to be read from path, practical if e.g. only one replicum is needed
- postfix (str): postfix of the file to read, e.g. '.gfms.dat' for openQCD-files
- names (list): Alternative labeling for replicas/ensembles. Has to have the appropriate length.
- Zeuthen_flow (bool): (optional) If True, the Zeuthen flow is used for Qtop. Only possible for version=='sfqcd' If False, the Wilson flow is used.
- integer_charge (bool): If True, the charge is rounded towards the nearest integer on each config.
Returns
- result (Obs): Read topological charge
723def read_gf_coupling(path, prefix, c, dtr_cnfg=1, Zeuthen_flow=True, **kwargs): 724 """Read the gradient flow coupling based on sfqcd gradient flow measurements. See 1607.06423 for details. 725 726 Note: The current implementation only works for c=0.3 and T=L. The definition of the coupling in 1607.06423 requires projection to topological charge zero which is not done within this function but has to be performed in a separate step. 727 728 Parameters 729 ---------- 730 path : str 731 path of the measurement files 732 prefix : str 733 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat. 734 Ignored if file names are passed explicitly via keyword files. 735 c : double 736 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L. 737 dtr_cnfg : int 738 (optional) parameter that specifies the number of measurements 739 between two configs. 740 If it is not set, the distance between two measurements 741 in the file is assumed to be the distance between two configurations. 742 steps : int 743 (optional) Distance between two configurations in units of trajectories / 744 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 745 r_start : list 746 list which contains the first config to be read for each replicum. 747 r_stop : list 748 list which contains the last config to be read for each replicum. 749 files : list 750 specify the exact files that need to be read 751 from path, practical if e.g. only one replicum is needed 752 names : list 753 Alternative labeling for replicas/ensembles. 754 Has to have the appropriate length. 755 postfix : str 756 postfix of the file to read, e.g. '.gfms.dat' for openQCD-files 757 Zeuthen_flow : bool 758 (optional) If True, the Zeuthen flow is used for the coupling. If False, the Wilson flow is used. 759 """ 760 761 if c != 0.3: 762 raise Exception("The required lattice norm is only implemented for c=0.3 at the moment.") 763 764 plaq = _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version="sfqcd", obspos=6, sum_t=False, Zeuthen_flow=Zeuthen_flow, integer_charge=False, **kwargs) 765 C2x1 = _read_flow_obs(path, prefix, c, dtr_cnfg=dtr_cnfg, version="sfqcd", obspos=7, sum_t=False, Zeuthen_flow=Zeuthen_flow, integer_charge=False, **kwargs) 766 L = plaq.tag["L"] 767 T = plaq.tag["T"] 768 769 if T != L: 770 raise Exception("The required lattice norm is only implemented for T=L at the moment.") 771 772 if Zeuthen_flow is not True: 773 raise Exception("The required lattice norm is only implemented for the Zeuthen flow at the moment.") 774 775 t = (c * L) ** 2 / 8 776 777 normdict = {4: 0.012341170468270, 778 6: 0.010162691462430, 779 8: 0.009031614807931, 780 10: 0.008744966371393, 781 12: 0.008650917856809, 782 14: 8.611154391267955E-03, 783 16: 0.008591758449508, 784 20: 0.008575359627103, 785 24: 0.008569387847540, 786 28: 8.566803713382559E-03, 787 32: 0.008565541650006, 788 40: 8.564480684962046E-03, 789 48: 8.564098025073460E-03, 790 64: 8.563853943383087E-03} 791 792 return t * t * (5 / 3 * plaq - 1 / 12 * C2x1) / normdict[L]
Read the gradient flow coupling based on sfqcd gradient flow measurements. See 1607.06423 for details.
Note: The current implementation only works for c=0.3 and T=L. The definition of the coupling in 1607.06423 requires projection to topological charge zero which is not done within this function but has to be performed in a separate step.
Parameters
- path (str): path of the measurement files
- prefix (str):
prefix of the measurement files, e.g.
_id0_r0.ms.dat. Ignored if file names are passed explicitly via keyword files. - c (double): Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L.
- dtr_cnfg (int): (optional) parameter that specifies the number of measurements between two configs. If it is not set, the distance between two measurements in the file is assumed to be the distance between two configurations.
- steps (int): (optional) Distance between two configurations in units of trajectories / cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given
- r_start (list): list which contains the first config to be read for each replicum.
- r_stop (list): list which contains the last config to be read for each replicum.
- files (list): specify the exact files that need to be read from path, practical if e.g. only one replicum is needed
- names (list): Alternative labeling for replicas/ensembles. Has to have the appropriate length.
- postfix (str): postfix of the file to read, e.g. '.gfms.dat' for openQCD-files
- Zeuthen_flow (bool): (optional) If True, the Zeuthen flow is used for the coupling. If False, the Wilson flow is used.
1067def qtop_projection(qtop, target=0): 1068 """Returns the projection to the topological charge sector defined by target. 1069 1070 Parameters 1071 ---------- 1072 path : Obs 1073 Topological charge. 1074 target : int 1075 Specifies the topological sector to be reweighted to (default 0) 1076 1077 Returns 1078 ------- 1079 reto : Obs 1080 projection to the topological charge sector defined by target 1081 """ 1082 if qtop.reweighted: 1083 raise Exception('You can not use a reweighted observable for reweighting!') 1084 1085 proj_qtop = [] 1086 for n in qtop.deltas: 1087 proj_qtop.append(np.array([1 if round(qtop.r_values[n] + q) == target else 0 for q in qtop.deltas[n]])) 1088 1089 reto = Obs(proj_qtop, qtop.names, idl=[qtop.idl[name] for name in qtop.names]) 1090 return reto
Returns the projection to the topological charge sector defined by target.
Parameters
- path (Obs): Topological charge.
- target (int): Specifies the topological sector to be reweighted to (default 0)
Returns
- reto (Obs): projection to the topological charge sector defined by target
1093def read_qtop_sector(path, prefix, c, target=0, **kwargs): 1094 """Constructs reweighting factors to a specified topological sector. 1095 1096 Parameters 1097 ---------- 1098 path : str 1099 path of the measurement files 1100 prefix : str 1101 prefix of the measurement files, e.g. <prefix>_id0_r0.ms.dat 1102 c : double 1103 Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L 1104 target : int 1105 Specifies the topological sector to be reweighted to (default 0) 1106 dtr_cnfg : int 1107 (optional) parameter that specifies the number of trajectories 1108 between two configs. 1109 if it is not set, the distance between two measurements 1110 in the file is assumed to be the distance between two configurations. 1111 steps : int 1112 (optional) Distance between two configurations in units of trajectories / 1113 cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given 1114 version : str 1115 version string of the openQCD (sfqcd) version used to create 1116 the ensemble. Default is 2.0. May also be set to sfqcd. 1117 L : int 1118 spatial length of the lattice in L/a. 1119 HAS to be set if version != sfqcd, since openQCD does not provide 1120 this in the header 1121 r_start : list 1122 offset of the first ensemble, making it easier to match 1123 later on with other Obs 1124 r_stop : list 1125 last configurations that need to be read (per replicum) 1126 files : list 1127 specify the exact files that need to be read 1128 from path, practical if e.g. only one replicum is needed 1129 names : list 1130 Alternative labeling for replicas/ensembles. 1131 Has to have the appropriate length 1132 Zeuthen_flow : bool 1133 (optional) If True, the Zeuthen flow is used for Qtop. Only possible 1134 for version=='sfqcd' If False, the Wilson flow is used. 1135 1136 Returns 1137 ------- 1138 reto : Obs 1139 projection to the topological charge sector defined by target 1140 """ 1141 1142 if not isinstance(target, int): 1143 raise Exception("'target' has to be an integer.") 1144 1145 kwargs['integer_charge'] = True 1146 qtop = read_qtop(path, prefix, c, **kwargs) 1147 1148 return qtop_projection(qtop, target=target)
Constructs reweighting factors to a specified topological sector.
Parameters
- path (str): path of the measurement files
- prefix (str):
prefix of the measurement files, e.g.
_id0_r0.ms.dat - c (double): Smearing radius in units of the lattice extent, c = sqrt(8 t0) / L
- target (int): Specifies the topological sector to be reweighted to (default 0)
- dtr_cnfg (int): (optional) parameter that specifies the number of trajectories between two configs. if it is not set, the distance between two measurements in the file is assumed to be the distance between two configurations.
- steps (int): (optional) Distance between two configurations in units of trajectories / cycles. Assumed to be the distance between two measurements * dtr_cnfg if not given
- version (str): version string of the openQCD (sfqcd) version used to create the ensemble. Default is 2.0. May also be set to sfqcd.
- L (int): spatial length of the lattice in L/a. HAS to be set if version != sfqcd, since openQCD does not provide this in the header
- r_start (list): offset of the first ensemble, making it easier to match later on with other Obs
- r_stop (list): last configurations that need to be read (per replicum)
- files (list): specify the exact files that need to be read from path, practical if e.g. only one replicum is needed
- names (list): Alternative labeling for replicas/ensembles. Has to have the appropriate length
- Zeuthen_flow (bool): (optional) If True, the Zeuthen flow is used for Qtop. Only possible for version=='sfqcd' If False, the Wilson flow is used.
Returns
- reto (Obs): projection to the topological charge sector defined by target
1151def read_ms5_xsf(path, prefix, qc, corr, sep="r", **kwargs): 1152 """ 1153 Read data from files in the specified directory with the specified prefix and quark combination extension, and return a `Corr` object containing the data. 1154 1155 Parameters 1156 ---------- 1157 path : str 1158 The directory to search for the files in. 1159 prefix : str 1160 The prefix to match the files against. 1161 qc : str 1162 The quark combination extension to match the files against. 1163 corr : str 1164 The correlator to extract data for. 1165 sep : str, optional 1166 The separator to use when parsing the replika names. 1167 **kwargs 1168 Additional keyword arguments. The following keyword arguments are recognized: 1169 1170 - names (List[str]): A list of names to use for the replicas. 1171 - files (List[str]): A list of files to read data from. 1172 - idl (List[List[int]]): A list of idls per replicum, resticting data to the idls given. 1173 1174 Returns 1175 ------- 1176 Corr 1177 A complex valued `Corr` object containing the data read from the files. In case of boudary to bulk correlators. 1178 or 1179 CObs 1180 A complex valued `CObs` object containing the data read from the files. In case of boudary to boundary correlators. 1181 1182 1183 Raises 1184 ------ 1185 FileNotFoundError 1186 If no files matching the specified prefix and quark combination extension are found in the specified directory. 1187 IOError 1188 If there is an error reading a file. 1189 struct.error 1190 If there is an error unpacking binary data. 1191 """ 1192 1193 # found = [] 1194 files = [] 1195 names = [] 1196 1197 # test if the input is correct 1198 if qc not in ['dd', 'ud', 'du', 'uu']: 1199 raise Exception("Unknown quark conbination!") 1200 1201 if corr not in ["gS", "gP", "gA", "gV", "gVt", "lA", "lV", "lVt", "lT", "lTt", "g1", "l1"]: 1202 raise Exception("Unknown correlator!") 1203 1204 if "files" in kwargs: 1205 known_files = kwargs.get("files") 1206 else: 1207 known_files = [] 1208 files = _find_files(path, prefix, "ms5_xsf_" + qc, "dat", known_files=known_files) 1209 1210 if "names" in kwargs: 1211 names = kwargs.get("names") 1212 else: 1213 for f in files: 1214 if not sep == "": 1215 se = f.split(".")[0] 1216 for s in f.split(".")[1:-2]: 1217 se += "." + s 1218 names.append(se.split(sep)[0] + "|r" + se.split(sep)[1]) 1219 else: 1220 names.append(prefix) 1221 if 'idl' in kwargs: 1222 expected_idl = kwargs.get('idl') 1223 names = sorted(names) 1224 files = sorted(files) 1225 1226 cnfgs = [] 1227 realsamples = [] 1228 imagsamples = [] 1229 repnum = 0 1230 for file in files: 1231 with open(path + "/" + file, "rb") as fp: 1232 1233 t = fp.read(8) 1234 kappa = struct.unpack('d', t)[0] 1235 t = fp.read(8) 1236 csw = struct.unpack('d', t)[0] 1237 t = fp.read(8) 1238 dF = struct.unpack('d', t)[0] 1239 t = fp.read(8) 1240 zF = struct.unpack('d', t)[0] 1241 1242 t = fp.read(4) 1243 tmax = struct.unpack('i', t)[0] 1244 t = fp.read(4) 1245 bnd = struct.unpack('i', t)[0] 1246 1247 placesBI = ["gS", "gP", 1248 "gA", "gV", 1249 "gVt", "lA", 1250 "lV", "lVt", 1251 "lT", "lTt"] 1252 placesBB = ["g1", "l1"] 1253 1254 # the chunks have the following structure: 1255 # confignumber, 10x timedependent complex correlators as doubles, 2x timeindependent complex correlators as doubles 1256 1257 chunksize = 4 + (8 * 2 * tmax * 10) + (8 * 2 * 2) 1258 packstr = '=i' + ('d' * 2 * tmax * 10) + ('d' * 2 * 2) 1259 cnfgs.append([]) 1260 realsamples.append([]) 1261 imagsamples.append([]) 1262 for t in range(tmax): 1263 realsamples[repnum].append([]) 1264 imagsamples[repnum].append([]) 1265 if 'idl' in kwargs: 1266 left_idl = set(expected_idl[repnum]) 1267 while True: 1268 cnfgt = fp.read(chunksize) 1269 if not cnfgt: 1270 break 1271 asascii = struct.unpack(packstr, cnfgt) 1272 cnfg = asascii[0] 1273 idl_wanted = True 1274 if 'idl' in kwargs: 1275 idl_wanted = (cnfg in expected_idl[repnum]) 1276 left_idl = left_idl - set([cnfg]) 1277 if idl_wanted: 1278 cnfgs[repnum].append(cnfg) 1279 1280 if corr not in placesBB: 1281 tmpcorr = asascii[1 + 2 * tmax * placesBI.index(corr):1 + 2 * tmax * placesBI.index(corr) + 2 * tmax] 1282 else: 1283 tmpcorr = asascii[1 + 2 * tmax * len(placesBI) + 2 * placesBB.index(corr):1 + 2 * tmax * len(placesBI) + 2 * placesBB.index(corr) + 2] 1284 1285 corrres = [[], []] 1286 for i in range(len(tmpcorr)): 1287 corrres[i % 2].append(tmpcorr[i]) 1288 for t in range(int(len(tmpcorr) / 2)): 1289 realsamples[repnum][t].append(corrres[0][t]) 1290 for t in range(int(len(tmpcorr) / 2)): 1291 imagsamples[repnum][t].append(corrres[1][t]) 1292 if 'idl' in kwargs: 1293 left_idl = list(left_idl) 1294 if expected_idl[repnum] == left_idl: 1295 raise ValueError("None of the idls searched for were found in replikum of file " + file) 1296 elif len(left_idl) > 0: 1297 warnings.warn('Could not find idls ' + str(left_idl) + ' in replikum of file ' + file, UserWarning) 1298 repnum += 1 1299 s = "Read correlator " + corr + " from " + str(repnum) + " replika with idls" + str(realsamples[0][t]) 1300 for rep in range(1, repnum): 1301 s += ", " + str(realsamples[rep][t]) 1302 print(s) 1303 print("Asserted run parameters:\n T:", tmax, "kappa:", kappa, "csw:", csw, "dF:", dF, "zF:", zF, "bnd:", bnd) 1304 1305 # we have the data now... but we need to re format the whole thing and put it into Corr objects. 1306 1307 compObs = [] 1308 1309 for t in range(int(len(tmpcorr) / 2)): 1310 compObs.append(CObs(Obs([realsamples[rep][t] for rep in range(repnum)], names=names, idl=cnfgs), 1311 Obs([imagsamples[rep][t] for rep in range(repnum)], names=names, idl=cnfgs))) 1312 1313 if len(compObs) == 1: 1314 return compObs[0] 1315 else: 1316 return Corr(compObs)
Read data from files in the specified directory with the specified prefix and quark combination extension, and return a Corr object containing the data.
Parameters
- path (str): The directory to search for the files in.
- prefix (str): The prefix to match the files against.
- qc (str): The quark combination extension to match the files against.
- corr (str): The correlator to extract data for.
- sep (str, optional): The separator to use when parsing the replika names.
**kwargs: Additional keyword arguments. The following keyword arguments are recognized:
- names (List[str]): A list of names to use for the replicas.
- files (List[str]): A list of files to read data from.
- idl (List[List[int]]): A list of idls per replicum, resticting data to the idls given.
Returns
- Corr: A complex valued
Corrobject containing the data read from the files. In case of boudary to bulk correlators. - or
- CObs: A complex valued
CObsobject containing the data read from the files. In case of boudary to boundary correlators.
Raises
- FileNotFoundError: If no files matching the specified prefix and quark combination extension are found in the specified directory.
- IOError: If there is an error reading a file.
- struct.error: If there is an error unpacking binary data.