Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
NVIDIA
GitHub Repository: NVIDIA/cuda-q-academic
Path: blob/main/chemistry-simulations/aux_files/krylov/qchem/uccsd_init_param.py
583 views
1
try:
2
from pyscf import gto, scf, cc, mcscf, mp, solvent
3
except ValueError:
4
print('PySCF should be installed to use pyscf. Use pip install pyscf')
5
6
import numpy as np
7
8
9
###################################
10
def get_thetas_unpack_restricted(singles, doubles, n_occupied, n_virtual):
11
12
theta_1 = np.zeros((2 * n_occupied, 2 * n_virtual))
13
theta_2 = np.zeros(
14
(2 * n_occupied, 2 * n_occupied, 2 * n_virtual, 2 * n_virtual))
15
16
for p in range(n_occupied):
17
for q in range(n_virtual):
18
theta_1[2 * p, 2 * q] = singles[p, q]
19
theta_1[2 * p + 1, 2 * q + 1] = singles[p, q]
20
21
for p in range(n_occupied):
22
for q in range(n_occupied):
23
for r in range(n_virtual):
24
for s in range(n_virtual):
25
theta_2[2 * p, 2 * q, 2 * s, 2 * r] = doubles[p, q, r, s]
26
theta_2[2 * p + 1, 2 * q + 1, 2 * r + 1,
27
2 * s + 1] = doubles[p, q, r, s]
28
theta_2[2 * p, 2 * q + 1, 2 * r + 1, 2 * s] = doubles[p, q,
29
r, s]
30
theta_2[2 * p + 1, 2 * q, 2 * r, 2 * s + 1] = doubles[p, q,
31
r, s]
32
33
return theta_1, theta_2
34
35
36
##############################################
37
def uccsd_get_amplitude(single_theta, double_theta, n_electrons, n_qubits, UR):
38
39
# compute a packed list that contains relevant amplitude for the UCCSD.
40
# We store first single excitation amplitudes then double excitation amplitudes.
41
42
# `single_amplitude: [N_occ, N_virt] array storing the single excitation amplitude.`
43
# `double_amplitude: [N_occ, N_occ, N_virt, N_virt] array storing double excitation amplitude.`
44
45
if n_qubits % 2 != 0:
46
raise ValueError(
47
"Total number of spin molecular orbitals (number of qubits) should be even."
48
)
49
else:
50
n_spatial_orbitals = n_qubits // 2
51
52
#if n_electrons%2!=0 and spin>0:
53
if UR:
54
t1a, t1b = single_theta
55
t2aa, t2ab, t2bb = double_theta
56
t2ab = np.asarray(t2ab.transpose(0, 1, 3, 2), order='C')
57
58
n_occupied_alpha, n_virtual_alpha = t1a.shape
59
n_occupied_beta, n_virtual_beta = t1b.shape
60
61
singles_alpha = []
62
singles_beta = []
63
doubles_mixed = []
64
doubles_alpha = []
65
doubles_beta = []
66
67
for p in range(n_occupied_alpha):
68
for q in range(n_virtual_alpha):
69
singles_alpha.append(t1a[p, q])
70
71
for p in range(n_occupied_beta):
72
for q in range(n_virtual_beta):
73
singles_beta.append(t1b[p, q])
74
75
for p in range(n_occupied_alpha):
76
for q in range(n_occupied_beta):
77
for r in range(n_virtual_beta):
78
for s in range(n_virtual_alpha):
79
doubles_mixed.append(t2ab[p, q, r, s])
80
81
for p in range(n_occupied_alpha - 1):
82
for q in range(p + 1, n_occupied_alpha):
83
for r in range(n_virtual_alpha - 1):
84
for s in range(r + 1, n_virtual_alpha):
85
doubles_alpha.append(t2aa[p, q, r, s])
86
87
for p in range(n_occupied_beta - 1):
88
for q in range(p + 1, n_occupied_beta):
89
for r in range(n_virtual_beta - 1):
90
for s in range(r + 1, n_virtual_beta):
91
doubles_alpha.append(t2bb[p, q, r, s])
92
93
#`elif n_electrons%2==0 and spin==0:`
94
else:
95
n_occupied = n_electrons // 2
96
n_virtual = n_spatial_orbitals - n_occupied
97
98
single_amplitude, double_amplitude = get_thetas_unpack_restricted(
99
single_theta, double_theta, n_occupied, n_virtual)
100
101
singles_alpha = []
102
singles_beta = []
103
doubles_mixed = []
104
doubles_alpha = []
105
doubles_beta = []
106
107
occupied_alpha_indices = [i * 2 for i in range(n_occupied)]
108
virtual_alpha_indices = [i * 2 for i in range(n_virtual)]
109
110
occupied_beta_indices = [i * 2 + 1 for i in range(n_occupied)]
111
virtual_beta_indices = [i * 2 + 1 for i in range(n_virtual)]
112
113
# Same spin single excitation
114
for p in occupied_alpha_indices:
115
for q in virtual_alpha_indices:
116
singles_alpha.append(single_amplitude[p, q])
117
118
for p in occupied_beta_indices:
119
for q in virtual_beta_indices:
120
singles_beta.append(single_amplitude[p, q])
121
122
#Mixed spin double excitation
123
for p in occupied_alpha_indices:
124
for q in occupied_beta_indices:
125
for r in virtual_beta_indices:
126
for s in virtual_alpha_indices:
127
doubles_mixed.append(double_amplitude[p, q, r, s])
128
129
# same spin double excitation
130
n_occ_alpha = len(occupied_alpha_indices)
131
n_occ_beta = len(occupied_beta_indices)
132
n_virt_alpha = len(virtual_alpha_indices)
133
n_virt_beta = len(virtual_beta_indices)
134
135
for p in range(n_occ_alpha - 1):
136
for q in range(p + 1, n_occ_alpha):
137
for r in range(n_virt_alpha - 1):
138
for s in range(r + 1, n_virt_alpha):
139
140
# Same spin: all alpha
141
doubles_alpha.append(double_amplitude[occupied_alpha_indices[p], occupied_alpha_indices[q],\
142
virtual_alpha_indices[r], virtual_alpha_indices[s]])
143
144
for p in range(n_occ_beta - 1):
145
for q in range(p + 1, n_occ_beta):
146
for r in range(n_virt_beta - 1):
147
for s in range(r + 1, n_virt_beta):
148
149
# Same spin: all beta
150
doubles_beta.append(double_amplitude[occupied_beta_indices[p], occupied_beta_indices[q],\
151
virtual_beta_indices[r], virtual_beta_indices[s]])
152
153
return singles_alpha + singles_beta + doubles_mixed + doubles_alpha + doubles_beta
154
155
156
##############################
157
158
def get_parameters(xyz:str, spin:int, charge: int, basis:str, symmetry:bool=False, memory:float=4000,cycles:int=100, \
159
initguess:str='minao', UR:bool=False, nele_cas=None, norb_cas=None, MP2:bool=False, natorb:bool=False,\
160
ccsd:bool=False, without_solvent:bool=True, potfile:str=None, verbose:bool=False):
161
162
if verbose:
163
print(
164
'[pyscf] Computing initial guess parameters using the classical CCSD'
165
)
166
167
filename = xyz.split('.')[0]
168
mol = gto.M(atom=xyz,
169
spin=spin,
170
charge=charge,
171
basis=basis,
172
max_memory=memory,
173
symmetry=symmetry,
174
output=filename + '-pyscf.log',
175
verbose=4)
176
177
if without_solvent:
178
if UR:
179
myhf = scf.UHF(mol)
180
myhf.max_cycle = cycles
181
myhf.chkfile = filename + '-pyscf.chk'
182
myhf.init_guess = initguess
183
myhf.kernel()
184
185
norb = myhf.mo_coeff[0].shape[1]
186
if verbose:
187
print('[pyscf] Total number of alpha molecular orbitals = ',
188
norb)
189
norb = myhf.mo_coeff[1].shape[1]
190
if verbose:
191
print('[pyscf] Total number of beta molecular orbitals = ',
192
norb)
193
194
else:
195
myhf = scf.RHF(mol)
196
myhf.max_cycle = cycles
197
myhf.chkfile = filename + '-pyscf.chk'
198
myhf.init_guess = initguess
199
myhf.kernel()
200
201
norb = myhf.mo_coeff.shape[1]
202
if verbose:
203
print('[pyscf] Total number of orbitals = ', norb)
204
205
nelec = mol.nelectron
206
if verbose:
207
print('[pyscf] Total number of electrons = ', nelec)
208
if verbose:
209
print('[pyscf] HF energy = ', myhf.e_tot)
210
211
##########################
212
# MP2
213
##########################
214
if MP2:
215
216
if UR:
217
mymp = mp.UMP2(myhf)
218
mp_ecorr, mp_t2 = mymp.kernel()
219
if verbose:
220
print('[pyscf] UR-MP2 energy= ', mymp.e_tot)
221
222
if natorb:
223
# Compute natural orbitals
224
dma, dmb = mymp.make_rdm1()
225
noon_a, U_a = np.linalg.eigh(dma)
226
noon_b, U_b = np.linalg.eigh(dmb)
227
noon_a = np.flip(noon_a)
228
noon_b = np.flip(noon_b)
229
230
if verbose:
231
print(
232
'Natural orbital (alpha orbitals) occupation number from UR-MP2: '
233
)
234
if verbose:
235
print(noon_a)
236
if verbose:
237
print(
238
'Natural orbital (beta orbitals) occupation number from UR-MP2: '
239
)
240
if verbose:
241
print(noon_b)
242
243
natorbs = np.zeros(np.shape(myhf.mo_coeff))
244
natorbs[0, :, :] = np.dot(myhf.mo_coeff[0], U_a)
245
natorbs[0, :, :] = np.fliplr(natorbs[0, :, :])
246
natorbs[1, :, :] = np.dot(myhf.mo_coeff[1], U_b)
247
natorbs[1, :, :] = np.fliplr(natorbs[1, :, :])
248
249
else:
250
if spin != 0:
251
raise ValueError("WARN: ROMP2 is unvailable in pyscf.")
252
else:
253
mymp = mp.MP2(myhf)
254
mp_ecorr, mp_t2 = mymp.kernel()
255
if verbose:
256
print('[pyscf] R-MP2 energy= ', mymp.e_tot)
257
258
if natorb:
259
# Compute natural orbitals
260
noons, natorbs = mcscf.addons.make_natural_orbitals(
261
mymp)
262
if verbose:
263
print(
264
'Natural orbital occupation number from R-MP2: '
265
)
266
if verbose:
267
print(noons)
268
269
if ccsd:
270
271
if UR:
272
273
mc = mcscf.UCASCI(myhf, norb_cas, nele_cas)
274
frozen = []
275
frozen = [y for y in range(0, mc.ncore[0])]
276
frozen += [
277
y for y in range(mc.ncore[0] +
278
mc.ncas, len(myhf.mo_coeff[0]))
279
]
280
281
if natorb:
282
mycc = cc.UCCSD(myhf, frozen=frozen, mo_coeff=natorbs)
283
mycc.max_cycle = cycles
284
mycc.kernel()
285
if verbose:
286
print(
287
'[pyscf] UR-CCSD energy of the active space using natural orbitals= ',
288
mycc.e_tot)
289
290
else:
291
mycc = cc.UCCSD(myhf, frozen=frozen)
292
mycc.max_cycle = cycles
293
mycc.kernel()
294
if verbose:
295
print(
296
'[pyscf] UR-CCSD energy of the active space using molecular orbitals= ',
297
mycc.e_tot)
298
299
else:
300
if nele_cas is None:
301
mycc = cc.CCSD(myhf)
302
mycc.max_cycle = cycles
303
mycc.kernel()
304
if verbose:
305
print('[pyscf] Total R-CCSD energy = ', mycc.e_tot)
306
qubits_num = 2 * norb
307
init_params = uccsd_get_amplitude(mycc.t1, mycc.t2, nelec,
308
qubits_num, UR)
309
#`np.array(init_params).tofile(f'{filename}_params.dat')`
310
return init_params
311
312
else:
313
mc = mcscf.CASCI(myhf, norb_cas, nele_cas)
314
frozen = []
315
frozen += [y for y in range(0, mc.ncore)]
316
frozen += [
317
y for y in range(mc.ncore +
318
norb_cas, len(myhf.mo_coeff))
319
]
320
if natorb and (spin == 0):
321
mycc = cc.CCSD(myhf, frozen=frozen, mo_coeff=natorbs)
322
mycc.max_cycle = cycles
323
mycc.kernel()
324
if verbose:
325
print(
326
'[pyscf] R-CCSD energy of the active space using natural orbitals= ',
327
mycc.e_tot)
328
329
elif natorb and (spin != 0):
330
raise ValueError(
331
"WARN: Natural orbitals cannot be computed. ROMP2 is unvailable in pyscf."
332
)
333
334
else:
335
mycc = cc.CCSD(myhf, frozen=frozen)
336
mycc.max_cycle = cycles
337
mycc.kernel()
338
if verbose:
339
print(
340
'[pyscf] R-CCSD energy of the active space using molecular orbitals= ',
341
mycc.e_tot)
342
343
qubits_num = 2 * norb_cas
344
init_params = uccsd_get_amplitude(mycc.t1, mycc.t2,
345
nele_cas, qubits_num, UR)
346
#`np.array(init_params).tofile(f'{filename}_params.dat')`
347
return init_params
348
349
# With solvent
350
else:
351
nelec = mol.nelectron
352
if verbose:
353
print('[Pyscf] Total number of electrons = ', nelec)
354
355
# HF with PE model.
356
mf_pe = scf.RHF(mol)
357
mf_pe.init_guess = initguess
358
mf_pe = solvent.PE(mf_pe, potfile).run()
359
norb = mf_pe.mo_coeff.shape[1]
360
if verbose:
361
print('[Pyscf] Total number of orbitals = ', norb)
362
if verbose:
363
print('[Pyscf] Total HF energy with solvent:', mf_pe.e_tot)
364
if verbose:
365
print('[Pyscf] Polarizable embedding energy from HF: ',
366
mf_pe.with_solvent.e)
367
368
if MP2:
369
if spin != 0:
370
raise ValueError("WARN: ROMP2 is unvailable in pyscf.")
371
else:
372
mymp = mp.MP2(mf_pe)
373
mymp = solvent.PE(mymp, potfile)
374
mymp.run()
375
if verbose:
376
print('[pyscf] R-MP2 energy with solvent= ', mymp.e_tot)
377
if verbose:
378
print('[Pyscf] Polarizable embedding energy from MP: ',
379
mymp.with_solvent.e)
380
381
if natorb:
382
# Compute natural orbitals
383
noons, natorbs = mcscf.addons.make_natural_orbitals(mymp)
384
if verbose:
385
print(
386
'[Pyscf] Natural orbital occupation number from R-MP2: '
387
)
388
if verbose:
389
print(noons)
390
391
if ccsd:
392
if nele_cas is None:
393
mycc = cc.CCSD(mf_pe)
394
mycc = solvent.PE(mycc, potfile)
395
mycc.run()
396
if verbose:
397
print('[Pyscf] Total CCSD energy with solvent: ',
398
mycc.e_tot)
399
if verbose:
400
print('[Pyscf] Polarizable embedding energy from CCSD: ',
401
mycc.with_solvent.e)
402
qubits_num = 2 * norb
403
init_params = uccsd_get_amplitude(mycc.t1, mycc.t2, nelec,
404
qubits_num, UR)
405
#`np.array(init_params).tofile(f'{filename}_params.dat')```
406
return init_params
407
408
else:
409
mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas)
410
frozen = []
411
frozen += [y for y in range(0, mc.ncore)]
412
frozen += [
413
y for y in range(mc.ncore + norb_cas, len(mf_pe.mo_coeff))
414
]
415
416
if natorb and (spin == 0):
417
mycc = cc.CCSD(mf_pe, frozen=frozen, mo_coeff=natorbs)
418
mycc = solvent.PE(mycc, potfile)
419
mycc.run()
420
if verbose:
421
print(
422
'[pyscf] R-CCSD energy of the active space (using natural orbitals) with solvent= ',
423
mycc.e_tot)
424
else:
425
mycc = cc.CCSD(mf_pe, frozen=frozen)
426
mycc = solvent.PE(mycc, potfile)
427
mycc.run()
428
if verbose:
429
print(
430
'[pyscf] CCSD energy of the active space (using molecular orbitals) with solvent= ',
431
mycc.e_tot)
432
if verbose:
433
print(
434
'[Pyscf] Polarizable embedding energy from CCSD: ',
435
mycc.with_solvent.e)
436
437
qubits_num = 2 * norb_cas
438
init_params = uccsd_get_amplitude(mycc.t1, mycc.t2, nele_cas,
439
qubits_num, UR)
440
#`np.array(init_params).tofile(f'{filename}_params.dat')`
441
return init_params
442