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