source: ThirdParty/mpqc_open/src/lib/chemistry/qc/mbpt/cscphf.cc@ 72461c

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 72461c was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 13.1 KB
Line 
1//
2// cscphf.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Ida Nielsen <ida@kemi.aau.dk>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#include <math.h>
29#include <stdlib.h>
30#include <iostream>
31
32#include <util/misc/formio.h>
33#include <util/keyval/keyval.h>
34#include <math/scmat/matrix.h>
35#include <chemistry/molecule/molecule.h>
36#include <chemistry/qc/basis/basis.h>
37#include <chemistry/qc/mbpt/mbpt.h>
38
39using namespace std;
40using namespace sc;
41
42static void
43compute_alpha(int dim, double **AP, double **alpha,
44 double **P, double *eigval, int nocc, int nvir);
45
46//////////////////////////////////////////////////////////////////////////
47// Do a direct CPHF calculation in the AO basis; equations are formulated
48// in terms of the occ-vir block P2aj of the second order correction (P2) to
49// the MP2 density matrix (cf. Frisch et al., CPL 166, p. 275 (1990)).
50//
51// CPHF equations:
52// (I-A)P2aj - B = 0 (B(a,j) = L(a,j)/(eigval[a]-eigval[j]))
53// A is a matrix (dimension dimP*dimP),
54// P2aj and B are vectors (dimension dimP)
55// (P2aj is kept as a RefSCMatrix);
56// Only closed-shell cases handled; no orbitals can be frozen
57// On exit, P2aj has been computed.
58
59void
60MBPT2::cs_cphf(double **scf_vector,
61 double *Laj, double *eigval, RefSCMatrix& P2aj)
62{
63 double epsilon = cphf_epsilon_; //convergence criterion for P2aj
64
65 int i, j, k, l, a;
66 int niter;
67 int dimP = nocc*nvir;
68
69 Ref<SCMatrixKit> kit = basis()->matrixkit();
70
71 RefSCDimension nbasis_dim = ao_dimension()->blocks()->subdim(0);
72 RefSCDimension nvir_dim(new SCDimension(nvir,1));
73 nvir_dim->blocks()->set_subdim(0, new SCDimension(nvir));
74 RefSCDimension nocc_dim(new SCDimension(nocc,1));
75 nocc_dim->blocks()->set_subdim(0, new SCDimension(nocc));
76
77 RefSCMatrix Cv(nbasis_dim,nvir_dim,kit);
78 RefSCMatrix Co(nbasis_dim,nocc_dim,kit);
79 RefSCMatrix D_matrix(nbasis_dim,nbasis_dim,kit);
80 RefSCMatrix AP_matrix(nvir_dim,nocc_dim,kit); // holds A*P[i-1]
81 RefSCMatrix P_matrix(nvir_dim, nocc_dim, kit);
82 RefSymmSCMatrix G(nbasis_dim,kit);
83
84
85 double *projctn = new double[dimP];
86 double *P_sum_new = new double[dimP];
87 double *P_sum_old = new double[dimP];
88 double **AP_matrix_tot; // row is A*P[k]
89 double **P_tmp, **alpha_tmp, **AP_matrix_tmp;
90 double **P;
91 double *D;
92 double **alpha;
93 double *ptr1, *ptr2;
94 double *laj_ptr;
95 double dot_prod;
96 double coef;
97 double tmp_val1, tmp_val2;
98 double maxabs;
99
100 // Debug print
101 if (debug_)
102 ExEnv::out0() << indent << "Entered cphf" << endl;
103 // End of debug print
104
105 ////////////////////////////////////////////////////////////
106 // Allocate and initialize various variables
107 ////////////////////////////////////////////////////////////
108
109 AP_matrix_tot = new double*[1];
110 AP_matrix_tot[0] = new double[dimP];
111
112 alpha = new double*[1];
113 alpha[0] = new double[1];
114
115 P = new double*[1];
116 P[0] = new double[dimP];
117
118 D = new double[nbasis*nbasis];
119
120 // NB: Elements in Laj are ordered as (j*nvir + a)
121 // since this ordering has been used with benefit in
122 // MP2 gradient program
123 ptr1 = P[0];
124 ptr2 = P_sum_old;
125 for (a=0; a<nvir; a++) {
126 laj_ptr = &Laj[a];
127 for (j=0; j<nocc; j++) {
128 *ptr1++ = *laj_ptr/(eigval[a+nocc]-eigval[j]);
129 *ptr2++ = 0.0;
130 laj_ptr += nvir;
131 }
132 }
133
134 for (i=0; i<nbasis; i++) {
135 for (j=0; j<noso; j++) {
136 if (j<nocc) Co(i,j) = scf_vector[i][j];
137 else Cv(i,j-nocc) = scf_vector[i][j];
138 }
139 }
140
141 /////////////////////////////////////////////////////////////////
142 // Solve the CPHF equations (iteratively, with DIIS like method)
143 /////////////////////////////////////////////////////////////////
144
145 i = 0;
146 niter = 0;
147
148 const int maxiter = 30;
149 const int warniter = 1;
150 while (niter < maxiter) { // Allow max maxiter iterations
151
152 niter++;
153 i++;
154 if (debug_)
155 ExEnv::out0() << indent << scprintf("niter: %i\n", niter);
156
157 // First expand AP_matrix_tot, alpha and P with an extra row
158
159 AP_matrix_tmp = new double *[i+1];
160 if (!AP_matrix_tmp) {
161 ExEnv::errn() << "Could not allocate AP_matrix_tmp" << endl;
162 abort();
163 }
164
165 alpha_tmp = new double *[i+1];
166
167 if (!alpha_tmp) {
168 ExEnv::errn() << "Could not allocate alpha_tmp" << endl;
169 abort();
170 }
171
172 P_tmp = new double *[i+1];
173
174 if (!P_tmp) {
175 ExEnv::errn() << "Could not allocate P_tmp" << endl;
176 abort();
177 }
178
179 for (j=0; j<i; j++) {
180 AP_matrix_tmp[j] = AP_matrix_tot[j];
181 alpha_tmp[j] = alpha[j];
182 P_tmp[j] = P[j];
183 }
184
185 AP_matrix_tmp[i] = new double[dimP];
186 if (!AP_matrix_tmp[i]) {
187 ExEnv::errn() << scprintf("Could not allocate AP_matrix_tmp[i], i = %i",i) << endl;
188 abort();
189 }
190 delete[] AP_matrix_tot;
191 AP_matrix_tot = AP_matrix_tmp;
192
193 alpha_tmp[i] = new double[1];
194 if (!alpha_tmp[i]) {
195 ExEnv::errn() << scprintf("Could not allocate alpha_tmp[i], i = %i",i) << endl;
196 abort();
197 }
198 delete[] alpha;
199 alpha = alpha_tmp;
200
201 P_tmp[i] = new double[dimP];
202 if (!P_tmp[i]) {
203 ExEnv::errn() << scprintf("Could not allocate P_tmp[i], i = %i",i) << endl;
204 abort();
205 }
206 delete[] P;
207 P = P_tmp;
208
209 // Initialize P[i]
210 for (j=0; j<dimP; j++) P[i][j] = 0.0;
211
212 // Compute A*P[i-1] (called AP_matrix) which is required to get P[i]
213 // A*P[i-1] is treated as a matrix to facilitate its computation
214 // A*P[i-1] is put into row i-1 of AP_matrix_tot
215
216 ptr1 = P[i-1];
217 for (j=0; j<nvir; j++) {
218 for (k=0; k<nocc; k++) {
219 P_matrix->set_element(j,k,*ptr1++); // Convert P[i-1] to RefSCMatrix
220 }
221 }
222 D_matrix = Cv*P_matrix*Co.t();
223#if 0
224 D_matrix = D_matrix + D_matrix.t();
225 D_matrix->convert(D); // Convert D_matrix to double* D
226 make_cs_gmat(G, D);
227#else
228 RefSymmSCMatrix sD(D_matrix.rowdim(), kit);
229 sD.assign(0.0);
230 sD.accumulate_symmetric_sum(D_matrix);
231 make_cs_gmat_new(G, sD);
232#endif
233 AP_matrix = 2*Cv.t()*G*Co;
234
235 ptr1 = AP_matrix_tot[i-1];
236 for (j=0; j<nvir; j++) {
237 for (k=0; k<nocc; k++) {
238 tmp_val1 = AP_matrix->get_element(j,k)/(eigval[k]-eigval[j+nocc]);
239 AP_matrix->set_element(j,k,tmp_val1);
240 *ptr1++ = tmp_val1;
241 }
242 }
243 // End of AP_matrix computation
244
245 // Compute coefficients alpha[0],...,alpha[i-1]
246 compute_alpha(i, AP_matrix_tot, alpha, P, eigval, nocc, nvir);
247
248 // Compute the vector P_sum_new = alpha[0]P[0]+...+alpha[i-1]P[i-1]
249 ptr1 = P_sum_new;
250 for (j=0; j<dimP; j++) *ptr1++ = 0.0;
251 for (j=0; j<i; j++) {
252 tmp_val1 = alpha[j][0];
253 ptr1 = P_sum_new;
254 ptr2 = P[j];
255 for (k=0; k<dimP; k++) {
256 *ptr1++ += tmp_val1 * *ptr2++;
257 }
258 }
259
260
261 /////////////////////////////////////////////////////////////
262 // Test for convergence
263 // (based on RMS(P2aj_new - P2aj_old)
264 // and max abs. val. of element)
265 /////////////////////////////////////////////////////////////
266 ptr1 = P_sum_new;
267 ptr2 = P_sum_old;
268 tmp_val1 = 0.0;
269 maxabs = 0.0;
270 for (j=0; j<dimP; j++) {
271 tmp_val2 = *ptr1++ - *ptr2++;
272 tmp_val1 += tmp_val2*tmp_val2;
273 if (fabs(tmp_val2) > maxabs) maxabs = fabs(tmp_val2);
274 }
275 if (debug_) {
276 ExEnv::out0() << indent << scprintf("RMS(P2aj_new-P2aj_old) = %12.10lf",
277 sqrt((tmp_val1)/dimP))
278 << endl;
279 ExEnv::out0() << indent
280 << scprintf("max. abs. element of (P2aj_new-P2aj_old) = %12.10lf",
281 maxabs)
282 << endl;
283 }
284 if (sqrt(tmp_val1)/dimP < epsilon && maxabs < epsilon) break; // Converged
285
286 // Put P_sum_new into P_sum old
287 ptr1 = P_sum_new;
288 ptr2 = P_sum_old;
289 for (j=0; j<dimP; j++) {
290 *ptr2++ = *ptr1++;
291 }
292
293 // Compute projection of A*P[i-1] on P[0],...,P[i-1]
294
295 ptr1 = projctn;
296 for (j=0; j<dimP; j++) *ptr1++ = 0.0;
297 for (j=0; j<i; j++) {
298 dot_prod = 0.0;
299 ptr1 = P[j];
300 for (k=0; k<dimP; k++) {
301 tmp_val1 = *ptr1++;
302 dot_prod += tmp_val1*tmp_val1; // Compute dot product <P[j]|P[j]>
303 }
304 ptr1 = P[j];
305 coef = 0.0;
306 for (k=0; k<nvir; k++) {
307 for (l=0; l<nocc; l++) {
308 coef += *ptr1++ * AP_matrix->get_element(k,l);
309 }
310 }
311 coef /= dot_prod;
312 ptr1 = P[j];
313 ptr2 = projctn;
314 for (k=0; k<dimP; k++) {
315 *ptr2++ += coef * *ptr1++;
316 }
317 }
318
319 // Compute P[i] as A*P[i-1] - projctn
320
321 ptr1 = P[i];
322 ptr2 = projctn;
323 for (j=0; j<nvir; j++) {
324 for (k=0; k<nocc; k++) {
325 *ptr1++ = AP_matrix->get_element(j,k) - *ptr2++;
326 }
327 }
328
329 /////////////////////////////////////////////
330 // Test for convergence (based on norm(P[i])
331 /////////////////////////////////////////////
332 tmp_val1 = 0.0;
333 for (l=0; l<dimP; l++) {
334 tmp_val1 += P[niter][l]*P[niter][l];
335 }
336 tmp_val1 = sqrt(tmp_val1/dimP);
337 if (debug_)
338 ExEnv::out0() << indent
339 << scprintf("norm(P[niter]) = %12.10lf", tmp_val1) << endl;
340 if (tmp_val1 < epsilon) { // Converged (if norm of new vector is zero)
341 ExEnv::out0() << indent
342 << scprintf("CPHF: iter = %2d rms(P) = %12.10f eps = %12.10f",
343 niter, tmp_val1, epsilon)
344 << endl << endl;
345 break;
346 }
347
348 if (niter >= warniter) {
349 ExEnv::out0() << indent
350 << scprintf("CPHF: iter = %2d rms(P) = %12.10f eps = %12.10f",
351 niter, tmp_val1, epsilon)
352 << endl;
353 }
354
355 }
356
357 ///////////////////////////////////////////////////////////////
358 // If CPHF equations did not converge, exit with error message
359 ///////////////////////////////////////////////////////////////
360 if (niter == maxiter) {
361 ExEnv::out0() << indent
362 << "CPHF equations did not converge in " << maxiter << " iterations"
363 << endl;
364 abort();
365 }
366
367 /////////////////////////////////////////////////////
368 // The converged vector is in P_sum_new;
369 // Put elements into P2aj
370 // NB: Elements in P2aj are ordered as (a*nocc + j);
371 /////////////////////////////////////////////////////
372 ptr1 = P_sum_new;
373 for (i=0; i<nvir; i++) {
374 for (j=0; j<nocc; j++) {
375 P2aj->set_element(i,j,*ptr1++);
376 }
377 }
378
379 // Debug print
380 if (debug_)
381 ExEnv::out0() << indent << "Exiting cphf" << endl;
382 // End of debug print
383
384 // Deallocate various arrays
385 delete[] D;
386
387 for (i=0; i<niter+1; i++) {
388 delete[] AP_matrix_tot[i];
389 delete[] alpha[i];
390 delete[] P[i];
391 }
392 delete[] AP_matrix_tot;
393 delete[] alpha;
394 delete[] P;
395 delete[] projctn;
396 delete[] P_sum_new;
397 delete[] P_sum_old;
398}
399
400
401static void
402compute_alpha(int dim, double **AP, double **alpha,
403 double **P, double *eigval, int nocc, int nvir)
404{
405 //////////////////////////////////////////////////////
406 // Solve the linear system of equations C*X = B
407 // where C is RefSCMatrix and X and B are RefSCVector
408 // Put result (X) into array alpha
409 //////////////////////////////////////////////////////
410 int i, j, k;
411 int vect_dim = nocc*nvir;
412
413 double tmp1, tmp2;
414 double *ptr1, *ptr2;
415 double *norm = new double[dim]; // contains norms of vectors P[i], i=0,dim
416
417 Ref<SCMatrixKit> kit = SCMatrixKit::default_matrixkit();
418 RefSCDimension C_dim(new SCDimension(dim));
419
420 RefSCMatrix C(C_dim,C_dim,kit);
421 RefSCVector B(C_dim,kit);
422 RefSCVector X(C_dim,kit);
423
424 // Compute norms of vectors P[i] and put into norm
425 for (i=0; i<dim; i++) norm[i] = 0.0;
426 ptr1 = norm;
427 for (i=0; i<dim; i++) {
428 ptr2 = P[i];
429 for (j=0; j<vect_dim; j++) {
430 *ptr1 += *ptr2 * *ptr2;
431 ptr2++;
432 }
433 ptr1++;
434 }
435 for (i=0; i<dim; i++) norm[i] = sqrt(norm[i]);
436
437 // Construct matrix C
438 for (i=0; i<dim; i++) {
439 for (j=0; j<dim; j++) {
440 tmp1 = 0.0;
441 ptr1 = P[i];
442 ptr2 = AP[j];
443 for (k=0; k<vect_dim; k++) {
444 tmp1 -= *ptr1++ * *ptr2++;
445 }
446 if (i == j) {
447 ptr1 = P[i];
448 for (k=0; k<vect_dim; k++) {
449 tmp2 = *ptr1++;
450 tmp1 += tmp2*tmp2;
451 }
452 }
453 C->set_element(i,j,tmp1/(norm[i]*norm[j]));
454 }
455 }
456
457 // Construct vector B
458 B->set_element(0,norm[0]);
459 for (i=1; i<dim; i++) B->set_element(i,0.0);
460
461 // Compute X = inv(C)*B
462 X = C.i()*B;
463
464 // Put elements of X into alpha
465 for (i=0; i<dim; i++) {
466 alpha[i][0] = X->get_element(i)/norm[i];
467 }
468
469 delete[] norm;
470}
471
472////////////////////////////////////////////////////////////////////////////
473
474// Local Variables:
475// mode: c++
476// c-file-style: "CLJ-CONDENSED"
477// End:
Note: See TracBrowser for help on using the repository browser.