3
#include<libciomr/libciomr.h>
4
#include<libchkpt/chkpt.h>
6
#include<libint/libint.h>
14
#define VIRT_SHELL -1000000 /* This should cause program to segfault if arrays are overrun */
16
void compute_scf_opdm()
18
int i,j,k,l,mo,open_1st,openshell_count,closedmos;
19
int sh_i, sh_j, ioffset, joffset, nao_i, nao_j;
20
int *symblk_offset; /* The pointer to the first MO in the symmetry block */
21
int *mo2moshell; /* array maping MO number to the mo shell */
22
double *occ; /* occupation vector - num_so long */
23
double *shell_occ; /* occupation numbers for MO shells */
24
double **mo_lagr; /* MO lagrangian */
26
struct shell_pair* sp;
28
/*--- Compute offsets of symmetry blocks ---*/
29
symblk_offset = init_int_array(Symmetry.nirreps);
31
for(i=0;i<Symmetry.nirreps-1;i++)
32
symblk_offset[i+1] = symblk_offset[i] + MOInfo.orbspi[i];
34
/*----------------------------------------------------
35
Compute occupation vector for spin-restricted cases
36
----------------------------------------------------*/
37
if (UserOptions.reftype != uhf) {
38
occ = init_array(MOInfo.num_mo);
39
mo2moshell = init_int_array(MOInfo.num_mo);
40
closedmos = (MOInfo.num_moshells != MOInfo.num_openmoshells);
41
shell_occ = init_array(MOInfo.num_moshells);
44
if (UserOptions.reftype != twocon) { /* single-reference case */
45
openshell_count = (closedmos > 0);
46
for (i=0;i<Symmetry.nirreps;i++) {
47
mo = symblk_offset[i];
48
for (j=0;j<MOInfo.clsdpi[i];j++) {
53
if (MOInfo.openpi[i] > 0) {
54
for (j=0;j<MOInfo.openpi[i];j++) {
55
mo2moshell[mo] = openshell_count;
59
shell_occ[openshell_count] = 1.0;
62
for (j=0;j<MOInfo.orbspi[i]-MOInfo.clsdpi[i]-MOInfo.openpi[i];j++) {
63
mo2moshell[mo] = VIRT_SHELL;
68
else { /* TCSCF for closed shells */
69
openshell_count = (closedmos > 0);
71
for (i=0;i<Symmetry.nirreps;i++) {
72
mo = symblk_offset[i];
73
for (j=0;j<MOInfo.clsdpi[i];j++) {
78
if (MOInfo.openpi[i] > 0) {
79
for (j=0;j<MOInfo.openpi[i];j++) {
80
mo2moshell[mo] = openshell_count;
81
occ[mo] = MOInfo.tcscf_occ[k];
84
shell_occ[openshell_count] = MOInfo.tcscf_occ[k];
88
for (j=0;j<MOInfo.orbspi[i]-MOInfo.clsdpi[i]-MOInfo.openpi[i];j++) {
89
mo2moshell[mo] = VIRT_SHELL;
94
} /*--- Done with occupations ---*/
97
/*-----------------------------------
98
Allocate and compute total density
99
-----------------------------------*/
100
Dens = block_matrix(BasisSet.num_ao,BasisSet.num_ao);
101
if (UserOptions.reftype != uhf) {
102
for(i=0;i<BasisSet.num_ao;i++)
105
for(k=0;k<Symmetry.nirreps;k++) {
106
mo = symblk_offset[k];
107
for(l=0; l < (MOInfo.clsdpi[k]+MOInfo.openpi[k]); l++) {
108
tmp += occ[mo]*MOInfo.scf_evec[0][mo][i]*MOInfo.scf_evec[0][mo][j];
112
Dens[j][i] = Dens[i][j] = tmp;
116
/* UHF case : Alpha and Beta eigenvectors */
117
for(i=0;i<BasisSet.num_ao;i++)
120
for(k=0;k<Symmetry.nirreps;k++) {
121
mo = symblk_offset[k];
122
/*--- Doubly-occupied MOs : Alpha and Beta ---*/
123
for(l=0; l < MOInfo.clsdpi[k]; l++) {
124
tmp += MOInfo.scf_evec[0][mo][i]*
125
MOInfo.scf_evec[0][mo][j]
126
+ MOInfo.scf_evec[1][mo][i]*
127
MOInfo.scf_evec[1][mo][j];
130
/*--- Singly-occupied MOs : Alpha only ---*/
131
for(l=0; l < MOInfo.openpi[k]; l++) {
132
tmp += MOInfo.scf_evec[0][mo][i]*
133
MOInfo.scf_evec[0][mo][j];
137
Dens[j][i] = Dens[i][j] = tmp;
141
/*---------------------------------
142
Find maximal elements of Dens in
144
---------------------------------*/
145
if (BasisSet.shell_pairs)
146
for(sh_i=0;sh_i<BasisSet.num_shells;sh_i++) {
147
ioffset = BasisSet.shells[sh_i].fao-1;
148
nao_i = ioff[BasisSet.shells[sh_i].am];
149
for(sh_j=0;sh_j<BasisSet.num_shells;sh_j++) {
150
sp = &(BasisSet.shell_pairs[sh_i][sh_j]);
151
joffset = BasisSet.shells[sh_j].fao-1;
152
nao_j = ioff[BasisSet.shells[sh_j].am];
155
for(j=0;j<nao_j;j++) {
156
tmp = Dens[ioffset+i][joffset+j];
165
/*--------------------------------
166
Compute energy-weighted density
167
--------------------------------*/
168
Lagr = block_matrix(BasisSet.num_ao,BasisSet.num_ao);
169
if (UserOptions.reftype == rhf) {
170
/*--- In closed-shell case compute energy-weighted density from SCF eigenvalues ---*/
171
for(i=0;i<BasisSet.num_ao;i++)
174
for(k=0;k<Symmetry.nirreps;k++) {
175
mo = symblk_offset[k];
176
for(l=0; l < (MOInfo.clsdpi[k]+MOInfo.openpi[k]); l++) {
177
tmp += occ[mo]*MOInfo.scf_evals[0][mo]*
178
MOInfo.scf_evec[0][mo][i]*
179
MOInfo.scf_evec[0][mo][j];
183
Lagr[j][i] = Lagr[i][j] = tmp;
186
else if (UserOptions.reftype == uhf) {
187
/*--- Use both alpha and beta eigenvalues in UHF case ---*/
188
for(i=0;i<BasisSet.num_ao;i++)
191
for(k=0;k<Symmetry.nirreps;k++) {
192
mo = symblk_offset[k];
193
/*--- Doubly-occupied MOs : Alpha and Beta ---*/
194
for(l=0; l < MOInfo.clsdpi[k]; l++) {
195
tmp += MOInfo.scf_evals[0][mo]*
196
MOInfo.scf_evec[0][mo][i]*
197
MOInfo.scf_evec[0][mo][j]
198
+ MOInfo.scf_evals[1][mo]*
199
MOInfo.scf_evec[1][mo][i]*
200
MOInfo.scf_evec[1][mo][j];
203
/*--- Singly-occupied MOs : Alpha only ---*/
204
for(l=0; l < MOInfo.openpi[k]; l++) {
205
tmp += MOInfo.scf_evals[0][mo]*
206
MOInfo.scf_evec[0][mo][i]*
207
MOInfo.scf_evec[0][mo][j];
211
Lagr[j][i] = Lagr[i][j] = tmp;
214
else if (UserOptions.reftype == rohf || UserOptions.reftype == twocon) {
215
/*--- In a restricted open-shell case just transform the lagrangian to AO basis ---*/
216
mo_lagr = chkpt_rd_lagr();
217
for(i=0;i<BasisSet.num_ao;i++)
220
for(k=0;k<MOInfo.num_mo;k++)
221
for(l=0;l<MOInfo.num_mo;l++)
222
tmp += mo_lagr[k][l]*MOInfo.scf_evec[0][k][i]*MOInfo.scf_evec[0][l][j];
223
Lagr[j][i] = Lagr[i][j] = tmp;
227
/*----------------------------------------------
228
Compute MO shell densities for ROHF and TCSCF
229
----------------------------------------------*/
230
if (UserOptions.reftype == rohf || UserOptions.reftype == twocon) {
231
ShDens = (double ***) malloc(sizeof(double **)*MOInfo.num_moshells);
232
for(i=0;i<MOInfo.num_moshells;i++)
233
ShDens[i] = block_matrix(BasisSet.num_ao,BasisSet.num_ao);
234
for(i=0;i<BasisSet.num_ao;i++)
236
for(k=0;k<Symmetry.nirreps;k++) {
237
mo = symblk_offset[k];
238
for(l=0; l < (MOInfo.clsdpi[k]+MOInfo.openpi[k]); l++) {
239
ShDens[mo2moshell[mo]][j][i] = (ShDens[mo2moshell[mo]][i][j] +=
240
MOInfo.scf_evec[0][mo][i]*MOInfo.scf_evec[0][mo][j]);
246
/* Check if the total density is a sum of shell densities - REMOVE AFTER DONE TESTING */
247
for(i=0;i<BasisSet.num_ao;i++)
248
for(j=0;j<BasisSet.num_ao;j++) {
250
for(k=0;k<MOInfo.num_moshells;k++)
251
tmp += ShDens[k][i][j]*shell_occ[k];
252
if (fabs(tmp - Dens[i][j]) > 1.0e-12)
253
punt("Total density is not a sum of shell densities");
256
/*--- Do this dirty trick because some people decided to keep
257
open-shells of diff irreps separate ---*/
258
/*--- form a single open-shell if rohf and high-spin ---*/
259
/* if (UserOptions.reftype == rohf) {
260
i = (closedmos > 0) ? 1 : 0;
261
for(j=i+1;j<MOInfo.num_moshells;j++) {
262
for(k=0;k<BasisSet.num_ao;k++)
263
for(l=0;l<BasisSet.num_ao;l++)
264
ShDens[i][k][l] += ShDens[j][k][l];
265
free_block(ShDens[j]);
267
BasisSet.num_moshells = 1 + i;
270
if (UserOptions.print_lvl >= PRINT_OPDM) {
271
for(i=0;i<MOInfo.num_moshells;i++) {
272
fprintf(outfile," -Density matrix for shell %d in AO basis :\n",i);
273
print_mat(ShDens[i],BasisSet.num_ao,BasisSet.num_ao,outfile);
274
fprintf(outfile,"\n\n");
284
if (UserOptions.reftype != uhf) {
289
if (UserOptions.reftype == rohf || UserOptions.reftype == twocon)