@@ -195,18 +195,20 @@ def compute_energy(self):
195
195
e_dsrg = self .dsrg_solver .compute_energy ()
196
196
psi4 .core .set_scalar_variable ("UNRELAXED ENERGY" , e_dsrg )
197
197
198
- self .energies_environment [0 ] = {k : v for k , v in psi4 .core .variables ().items ()
199
- if 'ROOT' in k }
198
+ self .energies_environment [0 ] = {k : v for k , v in psi4 .core .variables ().items () if 'ROOT' in k }
200
199
201
200
# Spit out energy if reference relaxation not implemented
202
201
if not self .Heff_implemented :
203
202
self .relax_maxiter = 0
204
203
205
204
# Reference relaxation procedure
206
205
for n in range (self .relax_maxiter ):
207
- # Grab effective Hamiltonian in the active space
208
- # These active integrals are in the original basis (before semi-canonicalize in the init function),
209
- # so that the CI coefficients are comparable before and after DSRG dressing.
206
+ # Grab the effective Hamiltonian in the active space
207
+ # Note: The active integrals (ints_dressed) are in the original basis
208
+ # (before semi-canonicalization in the init function),
209
+ # so that the CI vectors are comparable before and after DSRG dressing.
210
+ # However, the ForteIntegrals object and the dipole integrals always refer to the current semi-canonical basis.
211
+ # so to compute the dipole moment correctly, we need to make the RDMs and orbital basis consistent
210
212
ints_dressed = self .dsrg_solver .compute_Heff_actv ()
211
213
212
214
# Spit out contracted SA-DSRG energy
@@ -217,11 +219,10 @@ def compute_energy(self):
217
219
self .energies .append ((e_dsrg , e_relax ))
218
220
break
219
221
220
- # Solve active space using dressed integrals
222
+ # Call the active space solver using the dressed integrals
221
223
self .active_space_solver .set_active_space_integrals (ints_dressed )
222
- # ints_dressed in original basis so that the CI vectors are comparable before/after DSRG
223
- # however, forte integrals and thus dipole integrals are in semi-canonical basis
224
- # to make dipole computed correctly, we need to make the orbital basis consistent
224
+ # pass to the active space solver the unitary transformation between the original basis
225
+ # and the current semi-canonical basis
225
226
self .active_space_solver .set_Uactv (self .Ua , self .Ub )
226
227
state_energies_list = self .active_space_solver .compute_energy ()
227
228
@@ -236,15 +237,15 @@ def compute_energy(self):
236
237
237
238
# Compute relaxed dipole
238
239
if self .do_dipole :
239
- self .rdms = self .active_space_solver .compute_average_rdms (self .state_weights_map , self .max_rdm_level ,
240
- self .rdm_type )
240
+ self .rdms = self .active_space_solver .compute_average_rdms (
241
+ self .state_weights_map , self .max_rdm_level , self .rdm_type
242
+ )
241
243
dm_u = ProcedureDSRG .grab_dipole_unrelaxed ()
242
244
dm_r = self .compute_dipole_relaxed ()
243
245
self .dipoles .append ((dm_u , dm_r ))
244
246
245
247
# Save energies that have been pushed to Psi4 environment
246
- self .energies_environment [n + 1 ] = {k : v for k , v in psi4 .core .variables ().items ()
247
- if 'ROOT' in k }
248
+ self .energies_environment [n + 1 ] = {k : v for k , v in psi4 .core .variables ().items () if 'ROOT' in k }
248
249
self .energies_environment [n + 1 ]["DSRG FIXED" ] = e_dsrg
249
250
self .energies_environment [n + 1 ]["DSRG RELAXED" ] = e_relax
250
251
@@ -254,26 +255,36 @@ def compute_energy(self):
254
255
255
256
# Continue to solve DSRG equations
256
257
257
- # - Compute RDMs (RDMs available if done relaxed dipole)
258
+ # - Compute RDMs from the active space solver (the RDMs are already available if we computed the relaxed dipole)
259
+ # These RDMs are computed in the original basis
258
260
if self .do_multi_state or (not self .do_dipole ):
259
- self .rdms = self .active_space_solver .compute_average_rdms (self .state_weights_map , self .max_rdm_level ,
260
- self .rdm_type )
261
+ self .rdms = self .active_space_solver .compute_average_rdms (
262
+ self .state_weights_map , self .max_rdm_level , self .rdm_type
263
+ )
261
264
262
- # - Transform RDMs to the semi-canonical orbitals of last step (because of integrals)
265
+ # - Transform RDMs to the semi-canonical basis used in the last step (stored in self.Ua/self.Ub)
266
+ # We do this because the integrals and amplitudes are all expressed in the previous semi-canonical basis
263
267
self .rdms .rotate (self .Ua , self .Ub )
264
268
265
269
# - Semi-canonicalize RDMs and orbitals
266
270
if self .do_semicanonical :
267
271
self .semi .semicanonicalize (self .rdms )
268
- # NOT read previous orbitals if fixing orbital ordering and phases failed
272
+ # Do NOT read previous orbitals if fixing orbital ordering and phases failed
269
273
if (not self .semi .fix_orbital_success ()) and self .Heff_implemented :
270
- psi4 .core .print_out ("\n DSRG checkpoint files removed due to the unsuccessful"
271
- " attempt to fix orbital phase and order." )
274
+ psi4 .core .print_out (
275
+ "\n DSRG checkpoint files removed due to the unsuccessful"
276
+ " attempt to fix orbital phase and order."
277
+ )
272
278
self .dsrg_solver .clean_checkpoints ()
273
- self .Ua ["ik" ] = self .Ua ["ij" ] * self .semi .Ua_t ()["jk" ]
274
- self .Ub ["ik" ] = self .Ub ["ij" ] * self .semi .Ub_t ()["jk" ]
275
279
276
- # - Compute DSRG energy
280
+ # update the orbital transformation matrix that connects the original orbitals
281
+ # to the current semi-canonical ones. We do this only if we did a semi-canonicalization
282
+ temp = self .Ua .clone ()
283
+ self .Ua ["ik" ] = temp ["ij" ] * self .semi .Ua_t ()["jk" ]
284
+ temp .copy (self .Ub )
285
+ self .Ub ["ik" ] = temp ["ij" ] * self .semi .Ub_t ()["jk" ]
286
+
287
+ # - Compute the DSRG energy
277
288
self .make_dsrg_solver ()
278
289
self .dsrg_setup ()
279
290
self .dsrg_solver .set_read_cwd_amps (not self .restart_amps ) # don't read from cwd if checkpoint available
@@ -379,10 +390,10 @@ def reorder_weights(self, state_ci_wfn_map):
379
390
380
391
# try to fix ms < 0
381
392
if twice_ms > 0 :
382
- state_spin = forte .StateInfo (state . nb (), state . na (),
383
- state .multiplicity (), - twice_ms ,
384
- state .irrep (), state .irrep_label (),
385
- state . gas_min (), state . gas_max () )
393
+ state_spin = forte .StateInfo (
394
+ state . nb (), state . na (), state .multiplicity (), - twice_ms , state . irrep (), state . irrep_label () ,
395
+ state .gas_min (), state .gas_max ()
396
+ )
386
397
if state_spin in self .state_weights_map :
387
398
self .state_weights_map [state_spin ] = weights_new
388
399
0 commit comments