116
140
Params.ncoord = 0;
117
141
ip_count(":DBOC:COORDS",&Params.ncoord,0);
118
142
if (Params.ncoord == 0)
119
done("Keyword COORDS should be a vector of 2-element vectors");
143
done("Keyword COORDS should be a vector of 3-element vectors");
120
144
Params.coords = new Params_t::Coord_t[Params.ncoord];
121
145
for(int coord=0; coord<Params.ncoord; coord++) {
123
147
ip_count(":DBOC:COORDS",&nelem,1,coord);
125
done("Keyword COORDS should be a vector of 2-element vectors");
149
done("Keyword COORDS should be a vector of 3-element vectors");
126
150
errcod = ip_data(":DBOC:COORDS","%d",&Params.coords[coord].index,2,coord,0);
127
151
if (Params.coords[coord].index < 0 || Params.coords[coord].index >= Molecule.natom*3)
128
152
done("Keyword COORDS contains an out-of-bounds index");
129
153
errcod = ip_data(":DBOC:COORDS","%lf",&Params.coords[coord].coeff,2,coord,1);
155
errcod = ip_string(":DBOC:COORDS",&tmpstr,2,coord,2);
156
if (!strcmp(tmpstr,"SYMM"))
157
Params.coords[coord].symm = true;
158
else if (!strcmp(tmpstr,"NONSYMM"))
159
Params.coords[coord].symm = false;
161
done("Keyword COORDS contains an illegal symmetry specifier");
163
Params.coords[coord].atom = Params.coords[coord].index/3;
164
Params.coords[coord].xyz = Params.coords[coord].index%3;
134
Params.coords = NULL;
168
Params.ncoord = 3*Molecule.nuniques;
169
Params.coords = new Params_t::Coord_t[Params.ncoord];
171
for(int ua=0; ua<Molecule.nuniques; ua++) {
172
int atom = Molecule.ua2a[ua];
173
for(int xyz=0; xyz<3; xyz++) {
174
Params.coords[coord].index = 3*atom + xyz;
175
Params.coords[coord].atom = atom;
176
Params.coords[coord].xyz = xyz;
177
Params.coords[coord].coeff = (double)Molecule.ua_degen[ua];
179
// Figure out whether the cartesian displacement is symmetric under the symmetry operations of the stabilizer of the molecule
180
// (i.e. intersection of the stabilizers of the nuclei, i.e. the subgroup which leaves the molecule invariant)
181
// If it isn't -- then plus and minus displacements along this coordinate are equivalent
183
Params.coords[coord].symm = false;
184
for(int G=0; G<Molecule.nirreps; G++) {
185
int G_in_stab = true;
186
for(int a=0; a<Molecule.natom; a++)
187
if ((Molecule.ict[G][a]-1) != a) // this operation isn't in the stabilizer
190
int Gxyz = (int) Molecule.cartrep[G][3*xyz+xyz]; // character of G in the basis of the displacement
192
Params.coords[coord].symm = true;
137
200
int isotopes_given = ip_exist(":DBOC:ISOTOPES",0);
207
284
for(int atom=0; atom<Molecule.natom; atom++)
208
285
atomic_mass[atom] /= _au2amu;
290
// Remove PSI3 prefixed file
292
remove_psi3_file(char* name)
294
char* execstr = (char*) malloc( sizeof(char) * (strlen("/bin/rm -f ") +
295
strlen(psi_file_prefix) +
298
sprintf(execstr,"/bin/rm -f %s.%s",psi_file_prefix,name);
303
// Removes files left by DETCI/DETCAS
307
remove_psi3_file("file14.dat");
308
remove_psi3_file("thetas.dat");
309
remove_psi3_file("diis.dat");
310
remove_psi3_file("orbs.dat");
314
// This function will run psi for the first displaced point along the coordinate,
315
// save the basis set information, and save CI vector, if necessary
317
// NOTE: It's assumed that the first displacement is always by -delta
319
void run_psi_firstdisp(int disp)
322
if (!strcmp(Params.wfn,"DETCI") || !strcmp(Params.wfn,"DETCAS")) {
325
char *inputcmd = new char[80];
326
sprintf(inputcmd,"input --geomdat %d",disp);
327
int errcod = system(inputcmd);
329
done("input failed");
331
errcod = system("psi3 --dboc --noinput --messy");
338
// Read in the "-delta" displaced basis
340
chkpt_init(PSIO_OPEN_OLD);
341
BasisSets[MinusDelta] = new BasisSet(PSIF_CHKPT);
342
// rotate the geometry back to the original frame and change shell centers
343
double **rref_m = chkpt_rd_rref();
344
double **geom_m = chkpt_rd_geom();
346
double **geom_m_ref = block_matrix(Molecule.natom,3);
347
mmult(geom_m,0,rref_m,0,geom_m_ref,0,Molecule.natom,3,3,0);
350
for(int a=0; a<Molecule.natom; a++)
351
BasisSets[MinusDelta]->set_center(a,geom_m_ref[a]);
353
// Read in the "-delta" displaced HF wavefunction
354
HFVectors[MinusDelta] = new HFWavefunction();
356
// For CI method rename the saved wave function
357
if (!strcmp(Params.wfn,"DETCI") || !strcmp(Params.wfn,"DETCAS")) {
358
SlaterDetVector *vec;
359
slaterdetvector_read(PSIF_CIVECT,"CI vector",&vec);
360
slaterdetvector_write(PSIF_CIVECT,CI_Vector_Labels[0],vec);
361
slaterdetvector_delete_full(vec);
367
void run_psi_otherdisp(int disp)
369
int disp_coord = (disp-1)%Params.disp_per_coord;
370
int coord = (disp-1)/Params.disp_per_coord;
371
int symm = Params.coords[coord].symm;
373
// If this is an odd displacement means it's a plus displacement. If plus and minus
374
// displacements are equivalent for this coord (symm == true) then an equivalent
375
// displacement has JUST been computed. No need to compute the wave function
376
// again -- just run input, get the rref, and save the wave function.
377
if (!symm || (symm && disp_coord%2 == 0)) {
378
char *inputcmd = new char[80];
379
sprintf(inputcmd,"input --geomdat %d",disp);
380
int errcod = system(inputcmd);
382
done("input failed");
384
errcod = system("psi3 --dboc --noinput --messy");
390
// Read in the new displaced HF wavefunction
391
HFVectors[disp_coord] = new HFWavefunction();
395
// Read in the previous displaced HF wavefunction
396
HFVectors[disp_coord] = new HFWavefunction();
398
// only need to update rref
399
char *inputcmd = new char[80];
400
sprintf(inputcmd,"input --savemos --geomdat %d",disp);
401
int errcod = system(inputcmd);
403
done("input failed");
407
chkpt_init(PSIO_OPEN_OLD);
408
double** rref_p = chkpt_rd_rref();
410
HFVectors[disp_coord]->set_rref(rref_p);
414
// For CI method rename the saved wave function
415
if (!strcmp(Params.wfn,"DETCI") || !strcmp(Params.wfn,"DETCAS")) {
416
SlaterDetVector *vec;
417
slaterdetvector_read(PSIF_CIVECT,"CI vector",&vec);
418
slaterdetvector_write(PSIF_CIVECT,CI_Vector_Labels[disp_coord],vec);
419
slaterdetvector_delete_full(vec);
426
// This function creates basis set objects for each displacement
428
void init_basissets(Params_t::Coord_t* coord)
431
int atom = coord->index/3;
432
int xyz = coord->index%3;
434
for(int i=0; i<3; i++)
435
AplusD[i] = BasisSets[MinusDelta]->get_center(atom, i);
436
AplusD[xyz] += 2.0*Params.delta;
437
BasisSets[PlusDelta] = new BasisSet(*BasisSets[MinusDelta]);
438
BasisSets[PlusDelta]->set_center(atom,AplusD);
440
if (Params.disp_per_coord == 4) {
443
for(int i=0; i<3; i++)
444
Aplus2D[i] = AplusD[i];
445
Aplus2D[xyz] += Params.delta;
446
BasisSets[Plus2Delta] = new BasisSet(*BasisSets[MinusDelta]);
447
BasisSets[Plus2Delta]->set_center(atom,Aplus2D);
451
for(int i=0; i<3; i++)
452
Aminus2D[i] = Aplus2D[i];
453
Aminus2D[xyz] -= 4.0*Params.delta;
454
BasisSets[Minus2Delta] = new BasisSet(*BasisSets[MinusDelta]);
455
BasisSets[Minus2Delta]->set_center(atom,Aminus2D);
460
// This function destroys basis set objects for each displacement
462
void delete_basissets(Params_t::Coord_t* coord)
464
BasisSets[MinusDelta]->~BasisSet();
465
BasisSets[PlusDelta]->~BasisSet();
466
if (Params.disp_per_coord == 4) {
467
BasisSets[Minus2Delta]->~BasisSet();
468
BasisSets[Plus2Delta]->~BasisSet();
473
// This function destroys HFWavefunction objects for each displacement
475
void delete_hfwfns(Params_t::Coord_t* coord)
477
HFVectors[MinusDelta]->~HFWavefunction();
478
HFVectors[PlusDelta]->~HFWavefunction();
479
if (Params.disp_per_coord == 4) {
480
HFVectors[Minus2Delta]->~HFWavefunction();
481
HFVectors[Plus2Delta]->~HFWavefunction();
488
double* atomic_mass = get_atomic_masses();
210
489
const int ndisp = Params.disp_per_coord * Params.ncoord;
211
490
double E_dboc = 0.0;
213
for(int disp=1; disp<=ndisp; disp++) {
214
Params_t::Coord_t* coord = &(Params.coords[(disp-1)/2]);
492
for(int disp=1; disp<=ndisp;) {
493
int current_coord = (disp-1)/Params.disp_per_coord;
494
Params_t::Coord_t* coord = &(Params.coords[current_coord]);
215
495
int atom = coord->index/3;
216
496
int xyz = coord->index%3;
497
const bool symm = coord->symm;
218
char *inputcmd = new char[80];
220
sprintf(inputcmd,"input --geomdat %d --noreorient --nocomshift",disp);
222
sprintf(inputcmd,"input --geomdat %d",disp);
224
int errcod = system(inputcmd);
226
done("input failed");
228
errcod = system("psi3 --dboc --noinput --messy");
499
run_psi_firstdisp(disp);
235
// Read in the "-" displaced basis
237
chkpt_init(PSIO_OPEN_OLD);
238
BasisDispM = new BasisSet(PSIF_CHKPT);
239
// rotate the geometry back to the original frame and change shell centers
240
double **rref_m = chkpt_rd_rref();
241
double **geom_m = chkpt_rd_geom();
243
double **geom_m_ref = block_matrix(Molecule.natom,3);
244
mmult(geom_m,0,rref_m,0,geom_m_ref,0,Molecule.natom,3,3,0);
247
for(int a=0; a<Molecule.natom; a++)
248
BasisDispM->set_center(a,geom_m_ref[a]);
250
// For CI method rename the saved wave function
251
if (!strcmp(Params.wfn,"DETCI") || !strcmp(Params.wfn,"DETCAS")) {
252
SlaterDetVector *vec;
253
slaterdetvector_read(PSIF_CIVECT,"CI vector",&vec);
254
slaterdetvector_write(PSIF_CIVECT,"Old CI vector",vec);
255
slaterdetvector_delete_full(vec);
258
// obtain "+"-displaced basis by shiting the "active" center in the
259
// "-"-displaced center by twice the displacement size
261
AplusD[0] = geom_m_ref[atom][0];
262
AplusD[1] = geom_m_ref[atom][1];
263
AplusD[2] = geom_m_ref[atom][2];
264
AplusD[xyz] += 2*Params.delta;
265
BasisDispP = new BasisSet(*BasisDispM);
266
BasisDispP->set_center(atom,AplusD);
269
sprintf(inputcmd,"input --savemos --geomdat %d --noreorient --nocomshift",disp);
271
sprintf(inputcmd,"input --savemos --geomdat %d",disp);
273
errcod = system(inputcmd);
275
done("input failed");
277
errcod = system("psi3 --dboc --noinput --messy");
283
double S = eval_derwfn_overlap();
284
double del2 = (S-1.0)/(2.0*Params.delta*Params.delta);
501
for(int i=1;i<Params.disp_per_coord; i++) {
502
run_psi_otherdisp(disp);
506
init_basissets(coord);
508
// The - sign comes from the integration by parts
509
double del2 = (-1.0)*eval_derwfn_overlap(symm);
285
510
int Z = (int)Molecule.zvals[atom];
286
511
// mass of nucleus = atomic mass - mass of electrons
287
512
double nuclear_mass = atomic_mass[atom] - Z;
288
513
double E_i = -del2/(2.0*nuclear_mass);
289
514
// multiply by the degeneracy factor
290
515
E_i *= coord->coeff;
291
if (Params.print_lvl > PrintLevels::print_intro) {
292
fprintf(outfile," +- wave function overlap = %25.15lf\n",S);
293
fprintf(outfile," <d2/dx2> = %25.15lf\n",del2);
294
fprintf(outfile," DBOC contribution from cartesian degree of freedom %d = %20.10lf a.u.\n\n",
516
if (Params.print_lvl >= PrintLevels::print_params) {
517
char xyz = 'x'; xyz = (coord->xyz == 1) ? 'y' : xyz; xyz = (coord->xyz == 2) ? 'z' : xyz;
518
fprintf(outfile," <d2/dx2> = %25.15lf\n", del2);
519
fprintf(outfile," DBOC contribution = %20.10lf a.u.\n\n", E_i);