1import math 2import re 3 4import numpy as np 5from qcelemental.exceptions import ValidationError 6from qcelemental.util import filter_comments 7 8 9def load_hessian(shess: str, dtype: str) -> np.ndarray: 10 """Construct a Hessian array from any recognized string format. 11 12 Parameters 13 ---------- 14 shess 15 Multiline string specification of Hessian in a recognized format. 16 dtype 17 {"fcmfinal", "cfour", "gamess"} 18 Hessian format name. 19 20 Returns 21 ------- 22 np.ndarray 23 Hessian array in square shape. 24 25 """ 26 # list o'lines w/o comments or blanks 27 shess = filter_comments(shess) 28 lhess = list(filter(None, map(str.strip, shess.splitlines()))) 29 30 if dtype in ["fcmfinal", "cfour"]: 31 nat = int(lhess[0].split()[0]) 32 ndof = 3 * nat 33 datastr = "\n".join(lhess[1:]) 34 nhess = np.fromstring(datastr, sep=" ") 35 nhess = nhess.reshape(ndof, ndof) 36 elif dtype == "gamess": 37 if "ENERGY" in lhess[0]: 38 lhess.pop(0) 39 datastr = [] 40 for ln in lhess: 41 numbers = re.findall(r"([-+]?\d+\.\d+[DdEe][-+]\d\d)", ln) 42 if numbers: 43 datastr.extend(numbers) 44 45 nhess = np.fromstring(" ".join(datastr), sep=" ") 46 ndof = int(math.sqrt(len(nhess))) 47 nhess = nhess.reshape((ndof, ndof)) 48 else: 49 raise ValidationError("Unknown dtype: {}".format(dtype)) 50 51 return nhess 52 53 54def hess_to_string(hess, handle, dtype): 55 nat = hess.shape[0] // 3 56 assert hess.shape == (3 * nat, 3 * nat) 57 58 header = "{:5}{:5}".format(nat, 6 * nat) 59 np.savetxt(handle, hess.reshape((-1, 3)), fmt="%20.10f", delimiter="", newline="\n", header=header, comments="") 60