detcas: Orbital optimizer for detci


Files

file  calcinfo.h
 Enter brief description of file here.
file  detcas/cleanup.cc
 Enter brief description of file here.
file  detcas.cc
 Orbital optimizer for detci.
file  detcas/diis.cc
 Enter brief description of file here.
file  f_act.cc
 Enter brief description of file here.
file  detcas/get_mo_info.cc
 Enter brief description of file here.
file  globaldefs.h
 Enter brief description of file here.
file  detcas/globals.h
 Enter brief description of file here.
file  gradient.cc
 Enter brief description of file here.
file  hessian.cc
 Enter brief description of file here.
file  indpairs.cc
 Enter brief description of file here.
file  indpairs.h
 Enter brief description of file here.
file  detcas/ints.cc
 Enter brief description of file here.
file  detcas/params.cc
 Enter brief description of file here.
file  detcas/params.h
 Enter brief description of file here.
file  read_dens.cc
 Enter brief description of file here.
file  read_lag.cc
 Enter brief description of file here.
file  ref_orbs.cc
 Enter brief description of file here.
file  rotate_orbs.cc
 Enter brief description of file here.
file  setup_io.cc
 Enter brief description of file here.
file  setup_io.h
 Enter brief description of file here.
file  step.cc
 Enter brief description of file here.
file  test_bfgs.cc
 Enter brief description of file here.
file  thetas.cc
 Enter brief description of file here.

Functions

void psi::detcas::calc_gradient (void)
void psi::detcas::bfgs_hessian (void)
void psi::detcas::ds_hessian (void)
void psi::detcas::calc_hessian (void)
void psi::detcas::scale_gradient (void)
int psi::detcas::take_step (void)
void psi::detcas::rotate_orbs (void)
int psi::detcas::check_conv (void)

Detailed Description


Function Documentation

void psi::detcas::bfgs_hessian ( void   ) 

bfgs_hessian()

This function calculates a BFGS-updated MO/MO Hessian

C. David Sherrill March 2004

Definition at line 359 of file detcas.cc.

References block_matrix(), psi::detcas::calc_hessian(), init_array(), init_int_array(), invert_matrix(), print_mat(), psio_open(), psio_read_entry(), psio_tocscan(), and psio_write_entry().

00360 {
00361   int i, j, npairs;
00362   double fac, fad, fae, tval;
00363   double *dx, *dg, *hdg, **hess_copy, **hess_copy2, hess_det;
00364   int *idx;
00365 
00366   npairs = IndPairs.get_num_pairs();
00367 
00368   psio_open(PSIF_DETCAS, PSIO_OPEN_OLD);
00369 
00370   /* If no Hessian in the file */
00371   if (psio_tocscan(PSIF_DETCAS, "Hessian Inverse") == NULL) {
00372     calc_hessian();
00373     if (strcmp(Params.hessian, "FULL") != 0) {
00374       CalcInfo.mo_hess = block_matrix(npairs,npairs);
00375       for (i=0; i<npairs; i++) {
00376         CalcInfo.mo_hess[i][i] = 1.0 / CalcInfo.mo_hess_diag[i];
00377       }
00378     }
00379     else {
00380       hess_copy = block_matrix(npairs, npairs);
00381       idx = init_int_array(npairs);
00382       for (i=0; i<npairs; i++) {
00383         for (j=0; j<npairs; j++) {
00384           hess_copy[i][j] = CalcInfo.mo_hess[i][j];     
00385         }
00386       }
00387       ludcmp(hess_copy,npairs,idx,&hess_det);
00388 
00389       for (i=0;i<npairs;i++) hess_det *= hess_copy[i][i];
00390       fprintf(outfile,"The determinant of the hessian is %8.3E\n",hess_det);
00391 
00392       if (Params.level_shift) {
00393         while (hess_det < Params.determ_min) {
00394           fprintf(outfile, "Level shifting hessian by %8.3E\n", Params.shift);
00395           for (i=0; i<npairs; i++) {
00396             CalcInfo.mo_hess[i][i] += Params.shift;
00397             for (j=0; j<npairs; j++) {
00398               hess_copy[i][j] = CalcInfo.mo_hess[i][j];
00399             }
00400           }
00401           ludcmp(hess_copy,npairs,idx,&hess_det);
00402           for (i=0;i<npairs;i++) hess_det *= hess_copy[i][i];
00403           fprintf(outfile,"The determinant of the hessian is %8.3E\n",hess_det);
00404 
00405           for (i=0; i<npairs; i++) {
00406             for (j=0; j<npairs; j++) {
00407               hess_copy[i][j] = CalcInfo.mo_hess[i][j];
00408             }
00409           }
00410         }
00411       }
00412 
00413       /* n.b. this destroys hess_copy, and mo_hess now is INVERSE Hess */
00414       invert_matrix(hess_copy,CalcInfo.mo_hess,npairs,outfile);
00415 
00416       if (Params.print_lvl > 3) {
00417         fprintf(outfile, "\nInitial MO Hessian Inverse:\n");
00418         print_mat(CalcInfo.mo_hess,npairs,npairs,outfile);
00419         fprintf(outfile, "\n");
00420       }
00421 
00422       free(idx);
00423       free_block(hess_copy);
00424     } 
00425 
00426     /* write Hessian */
00427     psio_write_entry(PSIF_DETCAS, "Hessian Inverse", 
00428       (char *) CalcInfo.mo_hess[0], npairs*npairs*sizeof(double));
00429     /* write thetas */
00430     psio_write_entry(PSIF_DETCAS, "Thetas", (char *) CalcInfo.theta_cur,
00431       npairs*sizeof(double));
00432     /* write gradient */  
00433     psio_write_entry(PSIF_DETCAS, "MO Gradient", (char *) CalcInfo.mo_grad,
00434       npairs*sizeof(double));
00435     psio_close(PSIF_DETCAS, 1);
00436 
00437 
00438     return;
00439   } /* end initialization of BFGS data */
00440 
00441   dx = init_array(npairs);
00442   dg = init_array(npairs);
00443   hdg = init_array(npairs);
00444 
00445   /* read previous Hessian */
00446   CalcInfo.mo_hess = block_matrix(npairs,npairs);
00447   psio_read_entry(PSIF_DETCAS, "Hessian Inverse", (char *) CalcInfo.mo_hess[0], 
00448     npairs*npairs*sizeof(double));
00449 
00450   /* read previous thetas */
00451   psio_read_entry(PSIF_DETCAS, "Thetas", (char *) dx, npairs*sizeof(double));
00452 
00453   /* read previous gradient */
00454   psio_read_entry(PSIF_DETCAS, "MO Gradient", (char *) dg,
00455     npairs*sizeof(double));
00456 
00457   /* compute updated Hessian by BFGS procedure, see Numerical Recipies in C */
00458   
00459   /* get difference in thetas and gradient */
00460   for (i=0; i<npairs; i++) {
00461     dx[i] = CalcInfo.theta_cur[i] - dx[i];
00462     dg[i] = CalcInfo.mo_grad[i] - dg[i];
00463   }
00464 
00465   if (Params.print_lvl > 3) {
00466     fprintf(outfile, "Delta Theta and Delta Grad arrays:\n");
00467     for (i=0; i<npairs; i++) {
00468       fprintf(outfile, "%12.7lf   %12.7lf\n", dx[i], dg[i]);
00469     }
00470   }
00471 
00472   /* hdg = H^-1 * (grad(i+1) - grad(i)) */
00473   for (i=0; i<npairs; i++) {
00474     hdg[i] = 0.0;
00475     for (j=0; j<npairs; j++) {
00476       hdg[i] += CalcInfo.mo_hess[i][j] * dg[j];
00477     }
00478   }
00479 
00480   fac = fae = 0.0;
00481 
00482   for (i=0; i<npairs; i++) {
00483     fac += dg[i] * dx[i];
00484     fae += dg[i] * hdg[i];
00485   }
00486   fac = 1.0/fac;
00487   fad = 1.0/fae;
00488 
00489   /* the dg bit is the diff between BFGS and DFP */
00490   for (i=0; i<npairs; i++) dg[i] = fac*dx[i] - fad*hdg[i];
00491 
00492   for (i=0; i<npairs; i++) {
00493     for (j=0; j<npairs; j++) {
00494       CalcInfo.mo_hess[i][j] += fac*dx[i]*dx[j] - fad*hdg[i]*hdg[j]
00495          + fae*dg[i]*dg[j]; 
00496     }
00497   }
00498 
00499   if (Params.print_lvl > 3) {
00500     fprintf(outfile, "\nBFGS MO Hessian Inverse:\n");
00501     print_mat(CalcInfo.mo_hess,npairs,npairs,outfile);
00502     fprintf(outfile, "\n");
00503   }
00504 
00505   /* 
00506      this doesn't work unless you fix that dg is not overwritten above 
00507      when that's ensured, it seems to match 
00508    */
00509   /*
00510   if (Params.print_lvl > 3) {
00511     fprintf(outfile, "Check of dx = H dg\n");
00512     for (i=0; i<npairs; i++) {
00513       tval = 0.0;
00514       for (j=0; j<npairs; j++) {
00515         tval += CalcInfo.mo_hess[i][j] * dg[j];
00516       }
00517       fprintf(outfile, "%12.7lf vs %12.7lf\n", dx[i], tval);
00518     }
00519   }
00520   */
00521 
00522 
00523   idx = init_int_array(npairs);
00524   hess_copy = block_matrix(npairs, npairs);
00525   for (i=0; i<npairs; i++) {
00526     for (j=0; j<npairs; j++) {
00527       hess_copy[i][j] = CalcInfo.mo_hess[i][j];     
00528     }
00529   }
00530   ludcmp(hess_copy,npairs,idx,&hess_det);
00531   for (i=0; i<npairs; i++) hess_det *= CalcInfo.mo_hess[i][i];
00532   fprintf(outfile, "The determinant of the inverse Hessian is %8.3E\n",
00533     hess_det);
00534 
00535   /* just debug check */
00536   if (hess_det < 0.0) {
00537     hess_copy = block_matrix(npairs, npairs);
00538     hess_copy2 = block_matrix(npairs, npairs);
00539     for (i=0; i<npairs; i++) {
00540       for (j=0; j<npairs; j++) {
00541         hess_copy[i][j] = CalcInfo.mo_hess[i][j];     
00542       }
00543     }
00544 
00545     /* n.b. this destroys hess_copy */
00546     invert_matrix(hess_copy,hess_copy2,npairs,outfile);
00547 
00548     if (Params.print_lvl > 3) {
00549       fprintf(outfile, "\nMO Hessian:\n");
00550       print_mat(hess_copy2,npairs,npairs,outfile);
00551       fprintf(outfile, "\n");
00552     }
00553 
00554     ludcmp(hess_copy2,npairs,idx,&hess_det);
00555     for (i=0;i<npairs;i++) hess_det *= hess_copy2[i][i];
00556     fprintf(outfile,"The determinant of the hessian is %8.3E\n",hess_det);
00557 
00558       if (Params.level_shift) {
00559         while (hess_det < Params.determ_min) {
00560           fprintf(outfile, "Level shifting hessian by %8.3E\n", Params.shift);
00561           for (i=0; i<npairs; i++) {
00562             hess_copy2[i][i] += Params.shift;
00563             for (j=0; j<npairs; j++) {
00564               hess_copy[i][j] = hess_copy2[i][j];
00565             }
00566           }
00567           ludcmp(hess_copy,npairs,idx,&hess_det);
00568           for (i=0;i<npairs;i++) hess_det *= hess_copy[i][i];
00569           fprintf(outfile,"The determinant of the hessian is %8.3E\n",hess_det);                                                                                
00570           for (i=0; i<npairs; i++) {
00571             for (j=0; j<npairs; j++) {
00572               hess_copy2[i][j] = hess_copy[i][j];
00573             }
00574           }
00575         }
00576       }
00577                                                                                 
00578     /* n.b. this destroys hess_copy2, and mo_hess now is INVERSE Hess */
00579     invert_matrix(hess_copy2,CalcInfo.mo_hess,npairs,outfile);
00580 
00581     free_block(hess_copy2);
00582   }
00583 
00584   free_block(hess_copy);
00585 
00586   /* write thetas */
00587   psio_write_entry(PSIF_DETCAS, "Thetas", (char *) CalcInfo.theta_cur,
00588     npairs*sizeof(double));
00589   /* write gradient */  
00590   psio_write_entry(PSIF_DETCAS, "MO Gradient", (char *) CalcInfo.mo_grad,
00591     npairs*sizeof(double));
00592   /* write updated Hessian */
00593   psio_write_entry(PSIF_DETCAS, "Hessian Inverse", (char *) CalcInfo.mo_hess[0],
00594     npairs*npairs*sizeof(double));
00595   psio_close(PSIF_DETCAS, 1);
00596 
00597 
00598   free(idx);
00599   free(dx);
00600   free(dg);
00601   free(hdg);
00602 }

void psi::detcas::calc_gradient ( void   ) 

calc_gradient()

This function calculates the MO gradient from the MO Lagrangian

Definition at line 250 of file detcas.cc.

References block_matrix(), C_DSCAL(), init_array(), and print_mat().

00251 {
00252   int pair, npair, h, ir_npairs, ir_norbs, offset;
00253   double *ir_mo_grad, **ir_lag, *ir_theta_cur, value, rms;
00254   int *parr, *qarr, *ir_ppair, *ir_qpair;
00255   int p, q;
00256 
00257   npair = IndPairs.get_num_pairs();
00258   parr  = IndPairs.get_p_ptr();
00259   qarr  = IndPairs.get_q_ptr();
00260 
00261   CalcInfo.mo_grad = init_array(npair);
00262 
00263   /*
00264   calc_grad_1(npair, parr, qarr, CalcInfo.lag, CalcInfo.mo_grad);
00265   calc_grad_2(npair, parr, qarr, CalcInfo.onel_ints, CalcInfo.twoel_ints, 
00266               CalcInfo.opdm, CalcInfo.tpdm, CalcInfo.F_act, 
00267               (CalcInfo.num_cor_orbs + CalcInfo.num_fzc_orbs), 
00268               CalcInfo.npop, CalcInfo.mo_grad); 
00269   */
00270 
00271   // scratch array for dEdTheta, big enough for any irrep
00272   ir_mo_grad = init_array(npair);
00273   
00274   // calculate dEdU, then dEdTheta
00275   for (h=0,offset=0; h<CalcInfo.nirreps; h++) {
00276 
00277     // Setup for this irrep
00278     ir_npairs = IndPairs.get_ir_num_pairs(h);
00279     ir_norbs = CalcInfo.orbs_per_irr[h];
00280     if (h>0) offset += CalcInfo.orbs_per_irr[h-1];
00281     if (!ir_npairs) continue;
00282     ir_ppair = IndPairs.get_ir_prel_ptr(h);
00283     ir_qpair = IndPairs.get_ir_qrel_ptr(h);
00284     ir_lag = block_matrix(ir_norbs, ir_norbs);
00285     get_mat_block(CalcInfo.lag, ir_lag, ir_norbs, offset, CalcInfo.pitz2ci);
00286 
00287     if (Params.print_lvl > 3) {
00288       fprintf(outfile, "Irrep %d of lagrangian:\n", h);
00289       print_mat(ir_lag, ir_norbs, ir_norbs, outfile);
00290     }
00291 
00292     ir_theta_cur = IndPairs.get_irrep_vec(h, CalcInfo.theta_cur); 
00293 
00294     // Need to mult the Lagrangian by 2 to get dEdU
00295     C_DSCAL(ir_norbs*ir_norbs, 2.0, ir_lag[0], 1);
00296 
00297     if (Params.print_lvl > 3) {
00298       fprintf(outfile, "Irrep %d of 2 * lagrangian:\n", h);
00299       print_mat(ir_lag, ir_norbs, ir_norbs, outfile);
00300     }
00301 
00302     if (Params.use_thetas) {
00303       // Calc dEdU
00304       premult_by_U(h, CalcInfo.orbs_per_irr[h], ir_lag, ir_npairs,
00305                    ir_ppair, ir_qpair, ir_theta_cur);
00306 
00307       if (Params.print_lvl > 3) {
00308         fprintf(outfile, "dE/dU:\n", h);
00309         print_mat(ir_lag, ir_norbs, ir_norbs, outfile);
00310       }
00311 
00312       // Calculate dEdTheta
00313       calc_dE_dT(CalcInfo.orbs_per_irr[h], ir_lag, ir_npairs,
00314                  ir_ppair, ir_qpair, ir_theta_cur, ir_mo_grad);
00315     }
00316 
00317     /* non-theta version */
00318     else {
00319       for (pair=0; pair<ir_npairs; pair++) {
00320         p = ir_ppair[pair];  q = ir_qpair[pair];
00321         ir_mo_grad[pair] = ir_lag[p][q] - ir_lag[q][p];
00322       }
00323     }
00324 
00325     // Put dEdTheta into the large gradient array
00326     IndPairs.put_irrep_vec(h, ir_mo_grad, CalcInfo.mo_grad);
00327     delete [] ir_theta_cur;
00328     free_block(ir_lag); 
00329   }
00330 
00331 
00332   rms = 0.0;
00333   for (pair=0; pair<npair; pair++) {
00334     value =  CalcInfo.mo_grad[pair];
00335     rms += value * value;
00336   }
00337 
00338   if (Params.print_lvl > 2) 
00339     IndPairs.print_vec(CalcInfo.mo_grad, "\n\tOrbital Gradient:", outfile);
00340 
00341   rms = sqrt(rms);
00342   CalcInfo.mo_grad_rms = rms;
00343 
00344   if (Params.print_lvl)
00345     fprintf(outfile, "\n\tRMS Orbital Gradient: %6.4E\n", rms);
00346 }

void psi::detcas::calc_hessian ( void   ) 

calc_hessian()

This function calculates an approximate MO Hessian from the Fock matrix intermediates and two-electron integrals.

C. David Sherrill April 1998

Definition at line 737 of file detcas.cc.

References block_matrix(), init_array(), and print_mat().

Referenced by psi::detcas::bfgs_hessian(), and psi::detcas::ds_hessian().

00738 {
00739 
00740   int npairs, *ppair, *qpair, ncore;
00741 
00742   npairs = IndPairs.get_num_pairs();
00743   ppair = IndPairs.get_p_ptr();
00744   qpair = IndPairs.get_q_ptr();
00745 
00746   /* Now calculate the approximate diagonal MO Hessian */
00747   ncore = CalcInfo.num_fzc_orbs + CalcInfo.num_cor_orbs;
00748 
00749   if (strcmp(Params.hessian, "DIAG") == 0) {
00750     CalcInfo.mo_hess_diag = init_array(npairs);
00751     
00752     if (Params.use_fzc_h == 1) 
00753       form_diag_mo_hess(npairs, ppair, qpair, CalcInfo.onel_ints, 
00754         CalcInfo.twoel_ints, CalcInfo.opdm, CalcInfo.tpdm, CalcInfo.F_act, 
00755         ncore, CalcInfo.npop, CalcInfo.mo_hess_diag);
00756     else
00757       form_diag_mo_hess_yy(npairs, ppair, qpair, CalcInfo.onel_ints, 
00758         CalcInfo.twoel_ints, CalcInfo.opdm, CalcInfo.tpdm, CalcInfo.lag,
00759         CalcInfo.mo_hess_diag);
00760 
00761     if (Params.print_lvl > 3)  
00762       IndPairs.print_vec(CalcInfo.mo_hess_diag,"\n\tDiagonal MO Hessian:", 
00763         outfile);
00764   }
00765   else if (strcmp(Params.hessian, "APPROX_DIAG") == 0) {
00766     CalcInfo.mo_hess_diag = init_array(npairs);
00767     form_appx_diag_mo_hess(npairs, ppair, qpair, CalcInfo.onel_ints, 
00768                       CalcInfo.twoel_ints, CalcInfo.opdm, CalcInfo.tpdm, 
00769                       CalcInfo.F_act, ncore, CalcInfo.npop, 
00770                       CalcInfo.mo_hess_diag);
00771     if (Params.print_lvl > 3)  
00772       IndPairs.print_vec(CalcInfo.mo_hess_diag,"\n\tAppx Diagonal MO Hessian:", 
00773         outfile);
00774   }
00775   else if (strcmp(Params.hessian, "FULL") == 0) {
00776     CalcInfo.mo_hess = block_matrix(npairs,npairs);
00777     form_full_mo_hess(npairs, ppair, qpair, CalcInfo.onel_ints, 
00778       CalcInfo.twoel_ints, CalcInfo.opdm, CalcInfo.tpdm, CalcInfo.lag,
00779       CalcInfo.mo_hess);
00780     if (Params.print_lvl > 3) {
00781       fprintf(outfile, "\nMO Hessian:\n");
00782       print_mat(CalcInfo.mo_hess,npairs,npairs,outfile);
00783       fprintf(outfile, "\n");
00784     }
00785   }
00786   else {
00787     fprintf(outfile, "(detcas): Unrecognized Hessian option %s\n", 
00788       Params.hessian);
00789   }
00790  
00791 
00792 }

int psi::detcas::check_conv ( void   ) 

check_conv

Check the summary file to see if we've converged

Returns: 1 if converged, otherwise 0

Definition at line 981 of file detcas.cc.

References chkpt_close(), chkpt_init(), chkpt_rd_etot(), and ffile_noexit().

00982 {
00983   FILE *sumfile;
00984   char sumfile_name[] = "file14.dat";
00985   char comment[MAX_COMMENT];
00986   int i, entries, iter, nind;
00987   double rmsgrad, scaled_rmsgrad, energy, energy_last;
00988   int converged_energy=0, converged_grad=0, last_converged=0;
00989   double conv_rms_grad, conv_e;
00990 
00991   ffile_noexit(&sumfile,sumfile_name,2);
00992 
00993   if (sumfile == NULL) {
00994     CalcInfo.iter = 0;
00995     return(0);
00996   }
00997 
00998   if (fscanf(sumfile, "%d", &entries) != 1) {
00999     fprintf(outfile,"(print_step): Trouble reading num entries in file %s\n",
01000             sumfile_name);
01001     fclose(sumfile);
01002     CalcInfo.iter = 0;
01003     return(0);
01004   } 
01005 
01006   CalcInfo.iter = entries;
01007   for (i=0; i<entries; i++) {
01008     fscanf(sumfile, "%d %d %lf %lf %lf %s", &iter, &nind, &scaled_rmsgrad,
01009            &rmsgrad, &energy_last, comment);
01010   }
01011   fclose(sumfile);
01012 
01013   chkpt_init(PSIO_OPEN_OLD);
01014   energy = chkpt_rd_etot();
01015   chkpt_close();
01016 
01017   /* check for convergence */
01018   conv_rms_grad = pow(10.0, -(Params.rms_grad_convergence));
01019   conv_e = pow(10.0, -(Params.energy_convergence));
01020   if (rmsgrad < conv_rms_grad) converged_grad = 1;
01021   if (fabs(energy_last - energy) < conv_e)
01022     converged_energy = 1;
01023   if (strstr(comment, "CONV") != NULL)
01024     last_converged = 1;
01025 
01026   if (converged_grad && converged_energy && !last_converged) {
01027     fprintf(outfile, "\n\t*** Calculation Converged ***\n");
01028     return(1);
01029   }
01030   else {
01031     fprintf(outfile, "\n\t... calculation continuing ...\n");
01032     return(0);
01033   }
01034 }

void psi::detcas::ds_hessian ( void   ) 

ds_hessian()

This function calculates a Hessian update by a difference of gradients

C. David Sherrill March 2004

Definition at line 615 of file detcas.cc.

References psi::detcas::calc_hessian(), init_array(), psio_open(), psio_read_entry(), psio_tocscan(), and psio_write_entry().

00616 {
00617   int i, npairs;
00618   double tval;
00619   double *dx, *dg;
00620 
00621   npairs = IndPairs.get_num_pairs();
00622 
00623   psio_open(PSIF_DETCAS, PSIO_OPEN_OLD);
00624 
00625   /* If no Hessian in the file */
00626   if (psio_tocscan(PSIF_DETCAS, "Hessian") == NULL) {
00627     calc_hessian();
00628     if (strcmp(Params.hessian, "FULL") == 0) {
00629       CalcInfo.mo_hess_diag = init_array(npairs);
00630       for (i=0; i<npairs; i++) {
00631         CalcInfo.mo_hess_diag[i] = CalcInfo.mo_hess[i][i];
00632       }
00633     }
00634     for (i=0; i<npairs; i++) {
00635       if (CalcInfo.mo_hess_diag[i] < MO_HESS_MIN) {
00636         fprintf(outfile, "Warning: MO Hessian denominator too small\n");
00637         CalcInfo.mo_hess_diag[i] = MO_HESS_MIN;
00638       }
00639     }
00640 
00641     if (Params.print_lvl > 3) {
00642       fprintf(outfile, "\nInitial MO Hessian:\n");
00643       for (i=0; i<npairs; i++) 
00644         fprintf(outfile, "%12.6lf\n", CalcInfo.mo_hess_diag[i]);
00645       fprintf(outfile, "\n");
00646     }
00647 
00648     /* write Hessian */
00649     psio_write_entry(PSIF_DETCAS, "Hessian", 
00650       (char *) CalcInfo.mo_hess_diag, npairs*sizeof(double));
00651     /* write thetas */
00652     psio_write_entry(PSIF_DETCAS, "Thetas", (char *) CalcInfo.theta_cur,
00653       npairs*sizeof(double));
00654     /* write gradient */  
00655     psio_write_entry(PSIF_DETCAS, "MO Gradient", (char *) CalcInfo.mo_grad,
00656       npairs*sizeof(double));
00657     psio_close(PSIF_DETCAS, 1);
00658     return;
00659   } /* end initialization of data */
00660 
00661   dx = init_array(npairs);
00662   dg = init_array(npairs);
00663 
00664   /* read previous Hessian */
00665   CalcInfo.mo_hess_diag = init_array(npairs);
00666   psio_read_entry(PSIF_DETCAS, "Hessian", (char *) CalcInfo.mo_hess_diag, 
00667     npairs*sizeof(double));
00668 
00669   /* read previous thetas */
00670   psio_read_entry(PSIF_DETCAS, "Thetas", (char *) dx, npairs*sizeof(double));
00671 
00672   /* read previous gradient */
00673   psio_read_entry(PSIF_DETCAS, "MO Gradient", (char *) dg,
00674     npairs*sizeof(double));
00675 
00676   /* compute updated Hessian by David's recipie */
00677   
00678   /* get difference in thetas and gradient */
00679   for (i=0; i<npairs; i++) {
00680     dx[i] = CalcInfo.theta_cur[i] - dx[i];
00681     dg[i] = CalcInfo.mo_grad[i] - dg[i];
00682   }
00683 
00684   if (Params.print_lvl > 3) {
00685     fprintf(outfile, "Delta Theta and Delta Grad arrays:\n");
00686     for (i=0; i<npairs; i++) {
00687       fprintf(outfile, "%12.7lf   %12.7lf\n", dx[i], dg[i]);
00688     }
00689   }
00690 
00691   /* H = 1/2 [ H + (grad(i+1) - grad(i))/(x(i+1)-x(i)) ] */
00692   for (i=0; i<npairs; i++) {
00693     tval = dg[i] / dx[i];
00694     if (tval < - MO_HESS_MIN) tval = - MO_HESS_MIN;
00695     if (tval > 500.0) tval = 500.0;
00696     CalcInfo.mo_hess_diag[i] = 0.5 * (CalcInfo.mo_hess_diag[i] + tval);
00697     if (CalcInfo.mo_hess_diag[i] < MO_HESS_MIN) 
00698       CalcInfo.mo_hess_diag[i] = MO_HESS_MIN;
00699   }
00700 
00701   if (Params.print_lvl > 3) {
00702     fprintf(outfile, "\nDS MO Hessian:\n");
00703     for (i=0; i<npairs; i++) 
00704       fprintf(outfile, "%12.6lf\n", CalcInfo.mo_hess_diag[i]);
00705     fprintf(outfile, "\n");
00706   }
00707 
00708   /* write thetas */
00709   psio_write_entry(PSIF_DETCAS, "Thetas", (char *) CalcInfo.theta_cur,
00710     npairs*sizeof(double));
00711   /* write gradient */  
00712   psio_write_entry(PSIF_DETCAS, "MO Gradient", (char *) CalcInfo.mo_grad,
00713     npairs*sizeof(double));
00714   /* write updated Hessian */
00715   psio_write_entry(PSIF_DETCAS, "Hessian", (char *) CalcInfo.mo_hess_diag,
00716     npairs*sizeof(double));
00717   psio_close(PSIF_DETCAS, 1);
00718 
00719 
00720   free(dx);
00721   free(dg);
00722 }

void psi::detcas::rotate_orbs ( void   ) 

rotate_orbs()

Rotate the orbitals, irrep by irrep

Definition at line 913 of file detcas.cc.

References chkpt_close(), chkpt_init(), chkpt_wt_scf_irrep(), init_array(), and print_mat().

00914 {
00915   double *ir_theta;
00916   int h, pair, ir_norbs, ir_npairs, *ir_ppair, *ir_qpair;
00917 
00918   // First, we need to come up with Theta vectors for each irrep
00919   ir_theta = init_array(IndPairs.get_num_pairs());  // always big enough
00920   for (h=0; h<CalcInfo.nirreps; h++) {
00921     ir_npairs = IndPairs.get_ir_num_pairs(h);
00922     if (ir_npairs) {
00923       ir_norbs = CalcInfo.orbs_per_irr[h];
00924       ir_theta = IndPairs.get_irrep_vec(h, CalcInfo.theta_cur);
00925       ir_ppair  = IndPairs.get_ir_prel_ptr(h);
00926       ir_qpair  = IndPairs.get_ir_qrel_ptr(h);
00927       
00928       if (Params.print_lvl > 3) {
00929         fprintf(outfile, "Thetas for irrep %d\n", h);
00930         for (pair=0; pair<ir_npairs; pair++) {
00931           fprintf(outfile, "Pair (%2d,%2d) = %12.6lf\n",
00932                   ir_ppair[pair], ir_qpair[pair], ir_theta[pair]);
00933         }
00934         fprintf(outfile, "\n");
00935         fflush(outfile);
00936       }
00937 
00938       /* print old coefficients */
00939       if (Params.print_mos) {
00940         fprintf(outfile, "\n\tOld molecular orbitals for irrep %s\n", 
00941           CalcInfo.labels[h]);
00942         print_mat(CalcInfo.mo_coeffs[h], ir_norbs, ir_norbs, outfile);
00943       }
00944 
00945       if (Params.use_thetas)
00946         postmult_by_U(h, ir_norbs, CalcInfo.mo_coeffs[h], ir_npairs, 
00947           ir_ppair, ir_qpair, ir_theta);
00948       else
00949         postmult_by_exp_R(h, ir_norbs, CalcInfo.mo_coeffs[h], ir_npairs,
00950           ir_ppair, ir_qpair, ir_theta);
00951 
00952       /* print new coefficients */
00953       if (Params.print_mos) {
00954         fprintf(outfile, "\n\tNew molecular orbitals for irrep %s\n", 
00955           CalcInfo.labels[h]);
00956         print_mat(CalcInfo.mo_coeffs[h], ir_norbs, ir_norbs, outfile);
00957       }
00958 
00959 
00960       /* write the new block of MO coefficients to file30 */
00961       chkpt_init(PSIO_OPEN_OLD);
00962       chkpt_wt_scf_irrep(CalcInfo.mo_coeffs[h], h);
00963       chkpt_close();
00964       delete [] ir_theta;
00965     }
00966   }
00967 
00968 
00969 }

void psi::detcas::scale_gradient ( void   ) 

scale_gradient()

Scales the orbital gradient by the approximate orbital Hessian

Definition at line 803 of file detcas.cc.

References init_array().

00804 {
00805   int pair, npairs;
00806   double rms, value;
00807 
00808   npairs = IndPairs.get_num_pairs();
00809 
00810   CalcInfo.theta_step = init_array(npairs);
00811 
00812   // All this actually does is scale the gradient by the Hessian
00813   // If we have a diagonal (exact or approximate) Hessian
00814 
00815   // BFGS
00816   if (Params.scale_grad && Params.bfgs) {
00817     calc_orb_step_bfgs(npairs, CalcInfo.mo_grad, CalcInfo.mo_hess,
00818       CalcInfo.theta_step);
00819   }
00820   // non-BFGS diagonal Hessian
00821   else if (Params.scale_grad && (strcmp(Params.hessian,"DIAG")==0 || 
00822        strcmp(Params.hessian,"APPROX_DIAG")==0)) {
00823     calc_orb_step(npairs, CalcInfo.mo_grad, CalcInfo.mo_hess_diag,
00824       CalcInfo.theta_step);
00825   }
00826   // non-BFGS full Hessian
00827   else if ((Params.scale_grad && strcmp(Params.hessian,"FULL")==0) ||
00828     Params.bfgs) {
00829     calc_orb_step_full(npairs, CalcInfo.mo_grad, CalcInfo.mo_hess,
00830       CalcInfo.theta_step);
00831   }
00832   // No Hessian available: take unit step down gradient direction
00833   else {
00834     for (pair=0; pair<npairs; pair++) 
00835       CalcInfo.theta_step[pair] = CalcInfo.mo_grad[pair];
00836   }
00837     
00838 
00839   if (Params.print_lvl > 3)  
00840     IndPairs.print_vec(CalcInfo.theta_step,"\n\tScaled Orbital Grad:", outfile);
00841 
00842   rms = 0.0;
00843   for (pair=0; pair<npairs; pair++) {
00844     value =  CalcInfo.theta_step[pair];
00845     rms += value * value;
00846   }
00847 
00848   rms = sqrt(rms);
00849   CalcInfo.scaled_mo_grad_rms = rms;
00850  
00851   if (Params.print_lvl)
00852     fprintf(outfile, "\n\tScaled RMS Orbital Gradient: %6.4E\n", rms);
00853 
00854   if (Params.scale_step != 1.0) {
00855     for (pair=0; pair<npairs; pair++) 
00856       CalcInfo.theta_step[pair] *= Params.scale_step;
00857   }
00858 
00859 }

int psi::detcas::take_step ( void   ) 

take_step()

This function takes a step in orbital rotation (theta) space

Returns: type of step taken; 1=regular (Newton-Raphson), 2=diis

Definition at line 871 of file detcas.cc.

00872 {
00873   int npairs, pair, took_diis;
00874   
00875   npairs = IndPairs.get_num_pairs();
00876 
00877   /* for debugging purposes */
00878   if (Params.force_step) {
00879     CalcInfo.theta_cur[Params.force_pair] = Params.force_value;
00880     fprintf(outfile, "Forcing step for pair %d of size %8.3E\n",
00881       Params.force_pair, Params.force_value);
00882     return(1);
00883   }
00884 
00885   for (pair=0; pair<npairs; pair++) 
00886     CalcInfo.theta_cur[pair] += CalcInfo.theta_step[pair];
00887     //CalcInfo.theta_cur[pair] = CalcInfo.theta_step[pair];
00888 
00889   if (CalcInfo.iter >= Params.diis_start) 
00890     took_diis = diis(npairs, CalcInfo.theta_cur, CalcInfo.theta_step);
00891     //took_diis = diis(npairs, CalcInfo.theta_cur, CalcInfo.mo_grad);
00892   else 
00893     took_diis = 0;
00894 
00895   if (!took_diis) {
00896     if (Params.print_lvl) 
00897       fprintf(outfile, "Taking regular step\n");
00898   }
00899 
00900   return(took_diis+1);
00901 
00902 }


Generated on Wed Feb 13 16:36:15 2008 for PSI by  doxygen 1.5.4