Skip to content

Commit 2085ff8

Browse files
committed
Added the workflow function for interfacing Libra with PySCF; unfortunately, the current version still has a bug, so not yet ready to be used
1 parent 0296b5c commit 2085ff8

2 files changed

Lines changed: 150 additions & 0 deletions

File tree

src/libra_py/packages/pyscf/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from .implementations import CISD, CASSCF
55

66
__all__ = [
7+
"interfaces",
8+
"implementations",
9+
"methods",
710
"ElectronicStructureStrategy",
811
"MolecularGeometry",
912
"CISD",
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# *********************************************************************************
2+
# * Copyright (C) 2026 Jieyang Gu and Alexey V. Akimov
3+
# *
4+
# * This file is distributed under the terms of the GNU General Public License
5+
# * as published by the Free Software Foundation, either version 3 of
6+
# * the License, or (at your option) any later version.
7+
# * See the file LICENSE in the root directory of this distribution
8+
# * or <http://www.gnu.org/licenses/>.
9+
# *
10+
# *********************************************************************************/
11+
"""
12+
.. module:: methods
13+
:platform: Unix, Windows
14+
:synopsis: This module implements the Libra/PySCF interface function
15+
16+
.. moduleauthor::
17+
Alexey V. Akimov, Jieyang Gu
18+
19+
"""
20+
21+
22+
import os, sys, math, re, struct, copy, subprocess
23+
import numpy as np
24+
from liblibra_core import MATRIX, CMATRIX, CMATRIXList, Py2Cpp_int, Cpp2Py, Random
25+
26+
# Fisrt, we add the location of the library to test to the PYTHON path
27+
from libra_py.packages.pyscf.implementations.cisd import CISD
28+
from libra_py.packages.pyscf.implementations.casscf import CASSCF
29+
from libra_py.packages.pyscf.interfaces import ElectronicStructureStrategy, MolecularGeometry
30+
31+
from libra_py.packages.cp2k import methods as cp2k
32+
from libra_py import data_conv
33+
from libra_py import units
34+
35+
class tmp:
36+
pass
37+
38+
39+
def pyscf_compute_adi(q, params, full_id):
40+
41+
# ================= Decode trajectory index =================
42+
Id = Cpp2Py(full_id)
43+
itraj = Id[-1]
44+
45+
# ================= Extract coordinates =================
46+
coords = q.col(itraj)
47+
coordinates = data_conv.MATRIX2nparray(coords, float).reshape(-1,3)/units.Angst # in Angstrom
48+
49+
ndof = coords.num_of_rows
50+
nat = ndof // 3
51+
52+
# ================= Safe param access =================
53+
params.setdefault("is_first_time", {})
54+
params.setdefault("act_state", {})
55+
#params.setdefault("pyscf_obj", {})
56+
params.setdefault("coords_prev", {})
57+
58+
is_first_time = params["is_first_time"].get(itraj, True)
59+
act_state = params["act_state"].get(itraj, 0)
60+
61+
_basis = params.get("basis", "sto-3g")
62+
_charge = params.get("charge", 0)
63+
nstates = params.get("nstates", 2)
64+
method = params.get("method", "casscf")
65+
# The default is CAS(2,2)
66+
_norbcas = params.get("norbcas", 2)
67+
_nelecas = params.get("nelecas", 2)
68+
69+
# ================= Read parameters =================
70+
dt = float(params.get("dt", 41.0))
71+
_atom_labels = params["atom_labels"]
72+
73+
# ================= Previous coordinates =================
74+
75+
if is_first_time:
76+
coords_prev = copy.deepcopy(coordinates)
77+
else:
78+
coords_prev = copy.deepcopy(params["coords_prev"].get(itraj))
79+
80+
geom_prev = MolecularGeometry(atom_labels = _atom_labels, coords_angstrom=np.array(coords_prev) )
81+
geom = MolecularGeometry(atom_labels = _atom_labels, coords_angstrom=np.array(coordinates) )
82+
83+
84+
pyscf_obj = None
85+
if method=="casscf":
86+
pyscf_obj = CASSCF(norbcas=_norbcas, nelecas=_nelecas, nroots=nstates, basis=_basis, charge=_charge)
87+
elif method=="cisd":
88+
pyscf_obj = CISD(nroots=nstates, basis=_basis, charge=_charge)
89+
90+
91+
pyscf_obj.set_geom_and_run_hf(geom_prev)
92+
_ = [pyscf_obj.compute_energy(root) for root in range(nstates)]
93+
_ = [pyscf_obj.compute_gradient(root) for root in range(nstates)]
94+
95+
pyscf_obj.set_geom_and_run_hf(geom)
96+
energies = [pyscf_obj.compute_energy(root) for root in range(nstates)]
97+
grad = [pyscf_obj.compute_gradient(root) for root in range(nstates)]
98+
99+
# ================= Compute overlaps =================
100+
st_ci = pyscf_obj.time_overlap_matrix(nstates)
101+
102+
print(F"coords_prev = {coords_prev}")
103+
print(F"coordinates = {coordinates}")
104+
105+
# ================= Build object =================
106+
obj = tmp()
107+
obj.ham_adi = CMATRIX(nstates, nstates)
108+
obj.nac_adi = CMATRIX(nstates, nstates)
109+
obj.hvib_adi = CMATRIX(nstates, nstates)
110+
obj.basis_transform = CMATRIX(nstates, nstates)
111+
obj.time_overlap_adi = CMATRIX(nstates, nstates)
112+
113+
# ================= Populate Hamiltonian =================
114+
for i in range(nstates):
115+
obj.ham_adi.set(i, i, energies[i] * (1.0+0.0j) )
116+
obj.hvib_adi.set(i, i, energies[i] * (1.0+0.0j) )
117+
obj.basis_transform.set(i, i, 1.0+0.0j)
118+
119+
for j in range(nstates):
120+
obj.time_overlap_adi.set(i, j, float(st_ci[i, j]) * (1.0+0.0j) )
121+
122+
# ================== Forces ===============================
123+
obj.d1ham_adi = CMATRIXList()
124+
for idof in range(ndof):
125+
obj.d1ham_adi.append(CMATRIX(nstates, nstates))
126+
127+
for iatom in range(nat):
128+
for i in range(nstates):
129+
obj.d1ham_adi[3 * iatom + 0].set(i, i, grad[i][iatom, 0] * (1.0 + 0.0j))
130+
obj.d1ham_adi[3 * iatom + 1].set(i, i, grad[i][iatom, 1] * (1.0 + 0.0j))
131+
obj.d1ham_adi[3 * iatom + 2].set(i, i, grad[i][iatom, 2] * (1.0 + 0.0j))
132+
133+
# ================= Compute derivative couplings =================
134+
for i in range(nstates):
135+
for j in range(i + 1, nstates):
136+
dij = ( obj.time_overlap_adi.get(i, j) - obj.time_overlap_adi.get(j, i) ) / (2.0 * dt)
137+
obj.hvib_adi.set(i, j, -1j * dij)
138+
obj.hvib_adi.set(j, i, +1j * dij)
139+
140+
# ================= Store state =================
141+
#params["pyscf_obj"][itraj] = copy.deepcopy(pyscf_obj)
142+
#params["pyscf_obj"][itraj] = pyscf_obj
143+
params["coords_prev"][itraj] = copy.deepcopy(coordinates)
144+
params["is_first_time"][itraj] = False
145+
146+
return obj
147+

0 commit comments

Comments
 (0)