def test_nonstationary_hessian_hooh(): mol = psi4.geometry(""" 0 1 H 0.90 0.77 0.46 O 0.10 0.68 -0.02 O -0.10 -0.68 -0.02 H -0.90 -0.77 0.46 """) mol.update_geometry() Natom = mol.natom() psi4_options = {"basis": "cc-pvdz", "scf_type": "pk"} psi4.set_options(psi4_options) xyz = mol.geometry().to_array() coords = [ stre.Stre(0, 1), stre.Stre(2, 3), bend.Bend(0, 1, 2), bend.Bend(1, 2, 3), tors.Tors(0, 1, 2, 3) ] Z = [mol.Z(i) for i in range(0, Natom)] masses = [mol.mass(i) for i in range(0, Natom)] f1 = optking.frag.Frag(Z, xyz, masses, intcos=coords, frozen=False) OptMol = optking.molsys.Molsys([f1]) grad_x = psi4.gradient("hf").to_array().flatten() H_xy = psi4.hessian("hf").to_array() grad_q = OptMol.gradient_to_internals(grad_x) H_q = OptMol.hessian_to_internals(H_xy, grad_x) H_xy2 = OptMol.hessian_to_cartesians(H_q, grad_q) H_q2 = OptMol.hessian_to_internals(H_xy2, grad_x) assert psi4.compare_values(H_q, H_q2, 7, "Diff hessian cart->INT->cart->INT")
def test_stationary_hessian_hooh(): mol = psi4.geometry(""" 0 1 H 0.9047154509 0.7748902860 0.4679224940 O 0.1020360382 0.6887430144 -0.0294829672 O -0.1020360382 -0.6887430144 -0.0294829672 H -0.9047154509 -0.7748902860 0.4679224940 """) mol.update_geometry() Natom = mol.natom() psi4_options = {"basis": "cc-pvdz", "scf_type": "pk"} psi4.set_options(psi4_options) xyz = mol.geometry().to_array() coords = [ stre.Stre(0, 1), stre.Stre(2, 3), bend.Bend(0, 1, 2), bend.Bend(1, 2, 3), tors.Tors(0, 1, 2, 3) ] Z = [mol.Z(i) for i in range(0, Natom)] masses = [mol.mass(i) for i in range(0, Natom)] f1 = optking.frag.Frag(Z, xyz, masses, intcos=coords, frozen=False) OptMol = optking.molsys.Molsys([f1]) H_xy = psi4.hessian("hf").to_array() H_q = OptMol.hessian_to_internals(H_xy, useMasses=False) H_xy2 = OptMol.hessian_to_cartesians(H_q) H_q2 = OptMol.hessian_to_internals(H_xy2, useMasses=False) assert psi4.compare_values(H_q, H_q2, 7, "Diff hessian cart->INT->cart->INT")
def ComputeHessian(self): # Use PSI4 to calculate Hessian matrix psi4.core.set_output_file("hessian.out", False) psi4.geometry(self.geometry) #print(self.keywords) psi4.set_options(self.keywords) H = psi4.hessian(self.method) Hess = np.array(H) print(Hess.shape) self.displacement = Hess[:, self.mode] print(self.displacement.shape) self.grad = np.zeros(3 * self.natoms)
def calculate(inp, calc, save): '''Run nwchem on input, return data in results dict Args inp: Psi4 input object (geometry, bq_pos, bq_charges) calc: calculation type save: save calculation results Returns results: dictionary ''' options = params.options mol, bqfield, bqs = inp psi4.core.set_global_option_python('EXTERN', bqfield.extern) psi4.core.set_global_option('BASIS', options['basis']) psi4.set_memory(int(options['mem_mb'] * 1e6)) if options['correlation'] and calc not in ['esp', 'energy_hf']: theory = options['correlation'] psi4.core.set_global_option('freeze_core', 'True') else: theory = 'scf' method_str = theory + '/' + options['basis'] results = {} if calc == 'energy' or calc == 'energy_hf': results['E_tot'] = psi4.energy(method_str) elif calc == 'esp': raise RuntimeError("Not implemented") elif calc == 'gradient': grad, wfn = psi4.gradient(method_str, return_wfn=True) E = psi4.core.get_variable('CURRENT ENERGY') results['E'] = E results['gradient'] = psi4.p4util.mat2arr(grad) with open('grid.dat', 'w') as fp: for bq in bqs: fp.write('%16.10f%16.10f%16.10f\n' % (bq[0], bq[1], bq[2])) psi4.oeprop(wfn, 'GRID_FIELD') bq_field = np.loadtxt('grid_field.dat') assert bq_field.shape == (len(bqs), 3) bqgrad = [] for chg, field_vec in zip(bqs, bq_field): bqgrad.append(-1.0 * chg[3] * field_vec) results['bq_gradient'] = np.array(bqgrad) elif calc == 'hessian': hess = psi4.hessian(theory) hessarr = np.array(psi4.p4util.mat2arr(hess)) results['hess'] = hessarr return results
def test_hartree_fock_hessian(method='hf'): psi_deriv = np.round(np.asarray(psi4.hessian(method + '/' + basis_name)), 10) n = psi_deriv.shape[0] quax_deriv = np.asarray( quax.core.derivative(molecule, basis_name, method, deriv_order=2, options=options)).reshape(n, n) quax_partial00 = quax.core.partial_derivative(molecule, basis_name, method, deriv_order=2, partial=(0, 0)) assert np.allclose(psi_deriv, quax_deriv) assert np.allclose(psi_deriv[0, 0], quax_partial00)
def test_stationary_hessian_h2o(): mol = psi4.geometry(""" 0 1 O 0.0000000000 -0.0000000000 0.0025968676 H 0.0000000000 -0.7487897072 0.5811909492 H -0.0000000000 0.7487897072 0.5811909492 unit Angstrom """) psi4_options = {"basis": "cc-pvdz", "scf_type": "pk"} psi4.set_options(psi4_options) mol.update_geometry() Natom = mol.natom() xyz = mol.geometry().to_array() coords = [ stre.Stre(0, 1), stre.Stre(0, 2), bend.Bend(0, 1, 2), ] Z = [mol.Z(i) for i in range(0, Natom)] masses = [mol.mass(i) for i in range(0, Natom)] f1 = optking.frag.Frag(Z, xyz, masses, intcos=coords, frozen=False) OptMol = optking.molsys.Molsys([f1]) # Compute the Cartesian Hessian with psi4 H_xy = psi4.hessian("hf") # returns a (3N,3N) psi4 matrix #psi4.core.print_out("Calculated Cartesian hessian\n") #H_xy.print_out() # Transform hessian to internals with optking H_q = OptMol.hessian_to_internals(H_xy.to_array()) #returns ndarray #psi4.core.print_out(f"Hessian transformed into internal coordinates\n") #psi4.core.Matrix.from_array(H_q).print_out() ## Transform hessian to Cartesians with optking H_xy2 = OptMol.hessian_to_cartesians(H_q) # returns ndarray #print("Hessian transformed back into Cartesian coordinates") #print(H_xy2) assert psi4.compare_values(H_xy, H_xy2, 7, "Diff hessian CART->int->CART") H_q = OptMol.hessian_to_internals(H_xy.to_array(), useMasses=True) H_xy2 = OptMol.hessian_to_cartesians(H_q) assert psi4.compare_values(H_xy, H_xy2, 7, "Diff hessian CART->int->CART with u=1/mass")
def run_hessian(mol, bqfield, options): basis = 'aug-cc-pvdz' if 'basis' not in options else options['basis'] theory = 'mp2' if 'theory' not in options else options['theory'] psi4.core.set_global_option('freeze_core', 'True') method_str = theory + '/' + basis psi4.core.set_global_option_python('EXTERN', bqfield.extern) psi4.core.set_global_option('BASIS', basis) hess = psi4.hessian(theory) print "@QCBIM HESSIAN WRITTEN TO hess.dat" hessarr = np.array(psi4.p4util.mat2arr(hess)) M, N = hessarr.shape i = 0 with open('hess.dat', 'w') as fp: for row in range(M): for col in range(row + 1): fp.write('%24.16E\n' % hessarr[row, col]) i += 1 natom = mol.natom() assert i == 3 * natom + (3 * natom) * (3 * natom - 1) / 2
def compute_hessian(params, geom): # Use PSI4 to calculate Hessian matrix if (params.qm_program == "psi4"): psi4.core.set_output_file("hessian.out", False) mol = psi4.geometry(geom) psi4.set_options(params.keywords) psi4.set_num_threads(params.nthreads) H = psi4.hessian("%s/%s" % (params.method, params.basis)) Hess = np.array(H) if (params.qm_program == "sparrow"): sparrow_struct = open("sparrow_inp.xyz", "w+") sparrow_struct.write("%d\n" % params.natoms) sparrow_struct.write("Sparrow Structure Generated by PYREX\n") sparrow_geom = geom[5:] sparrow_struct.write(sparrow_geom) sparrow_struct.close() sparrow_interface.run_sparrow( "sparrow_inp.xyz", params.molecular_charge, params.molecular_multiplicity, params.method, "output.dat", "--hessian --suppress_normal_modes --output_to_file") Hess = sparrow_interface.sparrow_hessian(params.natoms, "hessian.dat") return Hess
def test_nonstationary_hessian_h2o(): mol = psi4.geometry(""" 0 1 O 0.0 -0.00 0.00 H 0.0 -0.75 0.58 H 0.0 0.75 0.58 unit Angstrom """) psi4_options = {"basis": "cc-pvdz", "scf_type": "pk"} psi4.set_options(psi4_options) mol.update_geometry() Natom = mol.natom() xyz = mol.geometry().to_array() coords = [ stre.Stre(0, 1), stre.Stre(0, 2), bend.Bend(0, 1, 2), ] Z = [mol.Z(i) for i in range(0, Natom)] masses = [mol.mass(i) for i in range(0, Natom)] f1 = optking.frag.Frag(Z, xyz, masses, intcos=coords, frozen=False) OptMol = optking.molsys.Molsys([f1]) grad_x = psi4.gradient("hf").to_array().flatten() H_xy = psi4.hessian("hf") H_q = OptMol.hessian_to_internals(H_xy.to_array(), grad_x, useMasses=False) grad_q = OptMol.gradient_to_internals(grad_x, useMasses=False) H_xy2 = OptMol.hessian_to_cartesians(H_q, grad_q) assert psi4.compare_values(H_xy, H_xy2, 8, "Diff hessian CART->int->CART") H_q = OptMol.hessian_to_internals(H_xy.to_array(), grad_x, useMasses=True) grad_q = OptMol.gradient_to_internals(grad_x, useMasses=True) H_xy2 = OptMol.hessian_to_cartesians(H_q, grad_q) assert psi4.compare_values(H_xy, H_xy2, 8, "Diff hessian CART->int->CART with u=1/masses")
for method in ['scf', 'mp2', 'ccsd(t)']: psi_deriv = onp.round( onp.asarray(psi4.gradient(method + '/' + basis_name)), 10) quax_deriv = onp.asarray( quax.core.derivative(molecule, basis_name, method, order=1)).reshape(-1, 3) print("\n{} gradients match: ".format(method), onp.allclose(quax_deriv, psi_deriv, rtol=0.0, atol=1e-6), '\n') print('Error:', np.abs(quax_deriv - psi_deriv)) print("\n") print("\n") print("Testing Hessians") for method in ['scf', 'mp2', 'ccsd(t)']: psi_deriv = onp.round( onp.asarray(psi4.hessian(method + '/' + basis_name, dertype='gradient')), 10) quax_deriv = onp.asarray( quax.core.derivative(molecule, basis_name, method, order=2)) print("\n{} hessians match: ".format(method), onp.allclose(quax_deriv, psi_deriv, rtol=0.0, atol=1e-4), '\n') print('Error:', np.abs(quax_deriv - psi_deriv)) print("\n") print("\n") #method = 'ccsd(t)' #psi_deriv = onp.round(onp.asarray(psi4.hessian(method + '/' + basis_name, dertype='gradient')), 10) #print("\nTesting partial Hessians at CCSD(T)") #quax_partial00 = quax.core.partial_derivative(molecule, basis_name, method, order=2, address=(0,0)) #quax_partial01 = quax.core.partial_derivative(molecule, basis_name, method, order=2, address=(0,1)) #quax_partial02 = quax.core.partial_derivative(molecule, basis_name, method, order=2, address=(0,2)) #quax_partial03 = quax.core.partial_derivative(molecule, basis_name, method, order=2, address=(0,3))
def compute_hessian(self, wfn, prog='psi4', geom=None, disp_points=3, disp_size=0.005, c4executable=None, c4kw={}): Natom = self.mol.natom() if prog.upper() == 'PSI4': self.pr("(ROA) Computing hessian with Psi4...\n") #Prepare geometry if geom is None: geom = self.analysis_geom_2D self.mol.set_geometry(core.Matrix.from_array(geom)) self.mol.fix_com(True) self.mol.fix_orientation(True) self.mol.reset_point_group('c1') # core.set_global_option('hessian_write', True) # compute the hessian, put in numpy format, then write out file15.dat file. psi4_hess = psi4.hessian(wfn, molecule=self.mol) npHess = psi4_hess.clone().np npHess = np.reshape(npHess, (3 * Natom * Natom, 3)) f = open('file15.dat', 'w') for i in range(npHess.shape[0]): f.write('{0:20.10f}{1:20.10f}{2:20.10f}\n'.format( npHess[i][0], npHess[i][1], npHess[i][2])) f.close() elif prog.upper() == 'CFOUR': self.pr("(ROA) Computing hessian with CFOUR...\n") kw = { 'CALC': wfn.upper(), # if basis not builtin C4, set BASIS=SPECIAL and SPECIAL_BASIS='name' 'BASIS': core.get_global_option('BASIS'), #'SPECIAL_BASIS' : '6-31G' 'VIB': 'EXACT', 'UNITS': 'BOHR', 'SCF_CONV': 9, 'MEM_UNIT': 'GB', 'MEMORY_SIZE': round(core.get_memory() // 1e9), 'SCF_DAMP': 600, # CFOUR's SCF is really poor at converging. 'SCF_EXPSTART': 300, 'SCF_MAXCYC': 600, } kw.update(c4kw) atom_symbols = [ self.mol.symbol(at) for at in range(self.mol.natom()) ] if c4executable is None: c4executable = 'run-cfour' c4 = CFOUR(self.analysis_geom_2D, atom_symbols, kw, title="hess-calc", executable=c4executable) c4.run() c4h = c4.parseHessian() # read the hessian output file (FCMFINAL) # Now rotate the Hessian into the original input orientation; fancy! c4coord = c4.parseGeometry() rmsd, mill = qcel.molutil.B787(c4coord, self.analysis_geom_2D, None, None, atoms_map=True, verbose=False) c4h[:] = mill.align_hessian(c4h) c4.writeFile15(c4h) else: raise Exception('Other hessian prog not yet implemented')
# Specify Molecule mol = psi4.geometry(""" O H 1 R H 1 R 2 104 symmetry c1 """) # physical constants changed, so geometry changes slightly from pkg_resources import parse_version if parse_version(psi4.__version__) >= parse_version("1.3a1"): mol.R = 1.1 * 0.52917721067 / 0.52917720859 else: mol.R = 1.1 psi4.core.set_active_molecule(mol) # Set Psi4 Options options = { 'BASIS': 'STO-3G', 'SCF_TYPE': 'PK', 'MP2_TYPE': 'CONV', 'E_CONVERGENCE': 1e-14, 'D_CONVERGENCE': 1e-14, 'print': 100 } psi4.set_options(options) scf_hess = psi4.hessian('SCF')
def run(input_json): # detect custom psi4, if we can psiapi_path = os.environ.get('PSIAPI_PATH') if psiapi_path: sys.path.insert(1, psiapi_path) import psi4 mol_json = input_json.pop('molecule') mc_json = input_json.pop('modelchem') output_json = {} output_json['raw_output'] = {} output_json['success'] = False output_json['output'] = {} # set some psi4 global stuff # Scratch files scr_path = os.environ.get("WORK") psi4_io = psi4.core.IOManager.shared_object() psi4_io.set_default_path(scr_path) # raw output file outfile_path = Path('output.dat') psi4.core.set_output_file(str(outfile_path), False) # node (or configured) memory and cores (after setting output file so the changes are registered there?) psi4.set_memory(str(cpu_info.memory()) + " MB") psi4.set_num_threads(cpu_info.ncore()) # set the basis basis = mc_json.get('basis') psi4.core.set_global_option('basis', basis) # set any other options for k, v in mc_json.get('program_options', {}).items(): psi4.core.set_global_option(k, v) try: # create the molecule psi_mol = psi4.geometry(vicMol(mol_json, dtype='json').to_string()) # extract name method = mc_json.get('method') driver = mc_json.get('driver') if driver == 'gradient': ret, wfn = psi4.gradient(method, return_wfn=True, molecule =psi_mol) elif driver == 'hessian': ret, wfn = psi4.hessian(method, return_wfn = True, molecule = psi_mol) elif driver == 'rotation': ret, wfn = psi4.properties(method, return_wfn = True, molecule = psi_mol, properties=['rotation']) else: raise RuntimeError("invalid driver {}: Validation should have caught this".format(driver)) grad = wfn.gradient() hess = wfn.hessian() rotations = extract_rotations(psi4.core.get_variables()) if hess: output_json['output']['hessian'] = util.pack_json_field(hess.to_array()) if grad: output_json['output']['gradient'] = util.pack_json_field(grad.to_array()) if rotations: output_json['output']['rotations'] = rotations output_json['output']['all_variables'] = psi4.core.get_variables() output_json['success'] = True output_json['raw_output']['outfile'] = outfile_path.read_text() return output_json except Exception as e: output_json['success'] = False output_json['raw_output']['error'] = "\n".join(traceback.format_exception(*sys.exc_info())) return output_json
optking.optparams.Params = optking.optparams.OptParams({}) from optking import stre, bend, tors bonds = [stre.Stre(*bond) for bond in bonds] angles = [bend.Bend(*angle) for angle in angles] dihedrals = [tors.Tors(*dihedral) for dihedral in dihedrals] coords = bonds + angles + dihedrals psi4.set_options(psi4_options) Z = [mol.Z(i) for i in range(0, mol.natom())] masses = [mol.mass(i) for i in range(0, mol.natom())] f1 = optking.frag.Frag(Z, xyz, masses, intcos=coords, frozen=False) OptMol = optking.molsys.Molsys([f1]) print(OptMol) # Compute the Cartesian Hessian with psi4 Hxyz = psi4.hessian('MP2') # returns a psi4 matrix print("Cartesian hessian") print(Hxyz.to_array()) # Transform hessian to internals with optking, returns a numpy array Hq = optking.intcosMisc.hessian_to_internals(Hxyz.to_array(), OptMol) print("Internal Coordinate Hessian") print(Hq) # Also print transformed Hessian to output File psi4.core.Matrix.from_array(Hq).print_out() # Note: there are probably better ways to print out the internal coordinate hessian that would minimize the amount of parsing needed in FFTK