source: ThirdParty/mpqc_open/src/lib/chemistry/qc/mbptr12/mbptr12.cc@ a844d8

Candidate_v1.6.1
Last change on this file since a844d8 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: 16.0 KB
Line 
1//
2// mbptr12.cc
3//
4// Copyright (C) 2001 Edward Valeev
5//
6// Author: Edward Valeev <edward.valeev@chemistry.gatech.edu>
7// Maintainer: EV
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#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <stdexcept>
33#include <sstream>
34#include <util/misc/string.h>
35
36#include <util/class/scexception.h>
37#include <util/misc/formio.h>
38#include <util/misc/exenv.h>
39#include <util/state/stateio.h>
40#include <math/scmat/blocked.h>
41#include <chemistry/qc/basis/petite.h>
42#include <chemistry/qc/scf/clhf.h>
43#include <chemistry/qc/cints/cints.h>
44#include <chemistry/qc/mbptr12/mbptr12.h>
45
46using namespace std;
47using namespace sc;
48
49/*--------------------------------
50 MBPT2_R12
51 --------------------------------*/
52
53static ClassDesc MBPT2_R12_cd(
54 typeid(MBPT2_R12),"MBPT2_R12",4,"public MBPT2",
55 0, create<MBPT2_R12>, create<MBPT2_R12>);
56
57MBPT2_R12::MBPT2_R12(StateIn& s):
58 MBPT2(s)
59{
60 r12eval_ << SavableState::restore_state(s);
61 r12a_energy_ << SavableState::restore_state(s);
62 r12ap_energy_ << SavableState::restore_state(s);
63 r12b_energy_ << SavableState::restore_state(s);
64 aux_basis_ << SavableState::restore_state(s);
65 vir_basis_ << SavableState::restore_state(s);
66 if (s.version(::class_desc<MBPT2_R12>()) >= 3) {
67 int gbc; s.get(gbc); gbc_ = (bool)gbc;
68 int ebc; s.get(ebc); ebc_ = (bool)ebc;
69 }
70 if (s.version(::class_desc<MBPT2_R12>()) >= 2) {
71 int absmethod; s.get(absmethod); abs_method_ = (LinearR12::ABSMethod)absmethod;
72 }
73 int stdapprox; s.get(stdapprox); stdapprox_ = (LinearR12::StandardApproximation) stdapprox;
74 int spinadapted; s.get(spinadapted); spinadapted_ = (bool)spinadapted;
75 if (s.version(::class_desc<MBPT2_R12>()) >= 4) {
76 int include_mp1; s.get(include_mp1); include_mp1_ = static_cast<bool>(include_mp1);
77 }
78 int r12ints_method; s.get(r12ints_method); r12ints_method_ = (R12IntEvalInfo::StoreMethod) r12ints_method;
79 s.get(r12ints_file_);
80 s.get(mp2_corr_energy_);
81 s.get(r12_corr_energy_);
82}
83
84MBPT2_R12::MBPT2_R12(const Ref<KeyVal>& keyval):
85 MBPT2(keyval)
86{
87 // Make sure can use the integral factory for linear R12
88 check_integral_factory_();
89
90 // Check is this is a closed-shell reference
91 CLHF* clhfref = dynamic_cast<CLHF*>(reference_.pointer());
92 if (!clhfref) {
93 ExEnv::err0() << "MBPT2_R12::MBPT2_R12: reference wavefunction is of non-CLHF type" << endl;
94 abort();
95 }
96
97 aux_basis_ = require_dynamic_cast<GaussianBasisSet*>(
98 keyval->describedclassvalue("aux_basis").pointer(),
99 "MBPT2_R12::MBPT2_R12\n"
100 );
101 if (aux_basis_.pointer() == NULL)
102 aux_basis_ = basis();
103
104 vir_basis_ = require_dynamic_cast<GaussianBasisSet*>(
105 keyval->describedclassvalue("vir_basis").pointer(),
106 "MBPT2_R12::MBPT2_R12\n"
107 );
108 if (vir_basis_.pointer() == NULL)
109 vir_basis_ = basis();
110
111 // Default is to assume GBC
112 gbc_ = keyval->booleanvalue("gbc",KeyValValueboolean((int)true));
113 // Default is to assume EBC
114 ebc_ = keyval->booleanvalue("ebc",KeyValValueboolean((int)true));
115
116 // For now the default is to use the old ABS method, of Klopper and Samson
117 char* abs_method_str = keyval->pcharvalue("abs_method",KeyValValuepchar("ABS"));
118 if ( !strcmp(abs_method_str,"KS") ||
119 !strcmp(abs_method_str,"ks") ||
120 !strcmp(abs_method_str,"ABS") ||
121 !strcmp(abs_method_str,"abs") ) {
122 abs_method_ = LinearR12::ABS_ABS;
123 }
124 else if ( !strcmp(abs_method_str,"KS+") ||
125 !strcmp(abs_method_str,"ks+") ||
126 !strcmp(abs_method_str,"ABS+") ||
127 !strcmp(abs_method_str,"abs+") ) {
128 abs_method_ = LinearR12::ABS_ABSPlus;
129 }
130 else if ( !strcmp(abs_method_str,"EV") ||
131 !strcmp(abs_method_str,"ev") ||
132 !strcmp(abs_method_str,"CABS") ||
133 !strcmp(abs_method_str,"cabs") ) {
134 abs_method_ = LinearR12::ABS_CABS;
135 }
136 else if ( !strcmp(abs_method_str,"EV+") ||
137 !strcmp(abs_method_str,"ev+") ||
138 !strcmp(abs_method_str,"CABS+") ||
139 !strcmp(abs_method_str,"cabs+") ) {
140 abs_method_ = LinearR12::ABS_CABSPlus;
141 }
142 else {
143 delete[] abs_method_str;
144 throw std::runtime_error("MBPT2_R12::MBPT2_R12 -- unrecognized value for abs_method");
145 }
146 delete[] abs_method_str;
147
148 // Default method is MBPT2-R12/A'
149 char *sa_string = keyval->pcharvalue("stdapprox",KeyValValuepchar("A'"));
150 if ( !strcmp(sa_string,"A") ||
151 !strcmp(sa_string,"a") ) {
152 stdapprox_ = LinearR12::StdApprox_A;
153 }
154 else if ( !strcmp(sa_string,"Ap") ||
155 !strcmp(sa_string,"ap") ||
156 !strcmp(sa_string,"A'") ||
157 !strcmp(sa_string,"a'") ) {
158 stdapprox_ = LinearR12::StdApprox_Ap;
159 }
160 else if ( !strcmp(sa_string,"B") ||
161 !strcmp(sa_string,"b") ) {
162 delete[] sa_string;
163 throw std::runtime_error("MBPT2_R12::MBPT2_R12() -- MP2-R12/B energy is not implemented yet");
164 }
165 else {
166 delete[] sa_string;
167 throw std::runtime_error("MBPT2_R12::MBPT2_R12() -- unrecognized value for stdapprox");
168 }
169
170 // Default is to use spin-adapted algorithm
171 spinadapted_ = keyval->booleanvalue("spinadapted",KeyValValueboolean((int)true));
172
173 // Default is to not compute MP1 energy
174 include_mp1_ = keyval->booleanvalue("include_mp1",KeyValValueboolean((int)false));
175
176 // Klopper and Samson's ABS method is only implemented for certain "old" methods
177 // Make sure that the ABS method is available for the requested MP2-R12 energy
178 const bool must_use_cabs = (!gbc_ || !ebc_ || stdapprox_ == LinearR12::StdApprox_B ||
179 !basis()->equiv(vir_basis_));
180 if (must_use_cabs &&
181 (abs_method_ == LinearR12::ABS_ABS || abs_method_ == LinearR12::ABS_ABSPlus))
182 throw std::runtime_error("MBPT2_R12::MBPT2_R12() -- abs_method must be set to cabs or cabs+ for this MP2-R12 method");
183
184 // Standard approximation A is not valid when gbc_ = false or ebc_ = false
185 if ( (!gbc_ || !ebc_) && stdapprox_ == LinearR12::StdApprox_A )
186 throw std::runtime_error("MBPT2_R12::MBPT2_R12() -- stdapprox=A is not valid when gbc_ = false or ebc_ = false");
187
188
189 // Determine how to store MO integrals
190 char *r12ints_str = keyval->pcharvalue("r12ints",KeyValValuepchar("mem-posix"));
191 if (!strcmp(r12ints_str,"mem")) {
192 r12ints_method_ = R12IntEvalInfo::mem_only;
193 }
194#if HAVE_MPIIO
195 else if (!strcmp(r12ints_str,"mem-mpi")) {
196 r12ints_method_ = R12IntEvalInfo::mem_mpi;
197 }
198 else if (!strcmp(r12ints_str,"mpi")) {
199 r12ints_method_ = R12IntEvalInfo::mpi;
200 }
201#else
202 else if ( !strcmp(r12ints_str,"mem-mpi") ||
203 !strcmp(r12ints_str,"mpi") ) {
204 throw std::runtime_error("MBPT2_R12::MBPT2_R12 -- the value for keyword r12ints is not valid in this environment (no MPI-I/O detected)");
205 }
206#endif
207 else if (!strcmp(r12ints_str,"mem-posix")) {
208 r12ints_method_ = R12IntEvalInfo::mem_posix;
209 }
210 else if (!strcmp(r12ints_str,"posix")) {
211 r12ints_method_ = R12IntEvalInfo::posix;
212 }
213 else {
214 delete[] r12ints_str;
215 throw std::runtime_error("MBPT2_R12::MBPT2_R12 -- invalid value for keyword r12ints");
216 }
217 delete[] r12ints_str;
218
219 // Make sure that integrals storage method is compatible with standard approximation
220 // If it's a MP2-R12/B calculation or EBC or GBC are not assumed then must use disk
221 const bool must_use_disk = (!gbc_ || !ebc_ || stdapprox_ == LinearR12::StdApprox_B);
222 if (must_use_disk && r12ints_method_ == R12IntEvalInfo::mem_only)
223 throw std::runtime_error("MBPT2_R12::MBPT2_R12 -- r12ints=mem is only possible for MP2-R12/A and MP2-R12/A' (GBC+EBC) methods");
224 if (must_use_disk) {
225 if (r12ints_method_ == R12IntEvalInfo::mem_posix)
226 r12ints_method_ = R12IntEvalInfo::posix;
227#if HAVE_MPIIO
228 if (r12ints_method_ == R12IntEvalInfo::mem_mpi)
229 r12ints_method_ = R12IntEvalInfo::mpi;
230#endif
231 }
232
233 // Get the prefix for the filename to store the integrals
234 std::ostringstream oss;
235 oss << SCFormIO::default_basename() << ".r12ints";
236 r12ints_file_ = keyval->stringvalue("r12ints_file",KeyValValuestring(oss.str()));
237
238 r12eval_ = 0;
239 r12a_energy_ = 0;
240 r12ap_energy_ = 0;
241 r12b_energy_ = 0;
242 mp2_corr_energy_ = 0.0;
243 r12_corr_energy_ = 0.0;
244
245 twopdm_grid_aa_ = require_dynamic_cast<TwoBodyGrid*>(keyval->describedclassvalue("twopdm_grid_aa").pointer(),
246 "MBPT2_R12::MBPT2_R12\n");
247 twopdm_grid_ab_ = require_dynamic_cast<TwoBodyGrid*>(keyval->describedclassvalue("twopdm_grid_ab").pointer(),
248 "MBPT2_R12::MBPT2_R12\n");
249}
250
251MBPT2_R12::~MBPT2_R12()
252{
253 r12eval_ = 0;
254 r12a_energy_ = 0;
255 r12ap_energy_ = 0;
256 r12b_energy_ = 0;
257}
258
259void
260MBPT2_R12::save_data_state(StateOut& s)
261{
262 MBPT2::save_data_state(s);
263 SavableState::save_state(r12eval_.pointer(),s);
264 SavableState::save_state(r12a_energy_.pointer(),s);
265 SavableState::save_state(r12ap_energy_.pointer(),s);
266 SavableState::save_state(r12b_energy_.pointer(),s);
267 SavableState::save_state(aux_basis_.pointer(),s);
268 SavableState::save_state(vir_basis_.pointer(),s);
269 s.put((int)gbc_);
270 s.put((int)ebc_);
271 s.put((int)abs_method_);
272 s.put((int)stdapprox_);
273 s.put((int)spinadapted_);
274 s.put((int)include_mp1_);
275 s.put((int)r12ints_method_);
276 s.put(r12ints_file_);
277
278 s.put(mp2_corr_energy_);
279 s.put(r12_corr_energy_);
280}
281
282void
283MBPT2_R12::print(ostream&o) const
284{
285 o << indent << "MBPT2_R12:" << endl;
286 o << incindent;
287 o << indent << "GBC assumed: " << (gbc_ ? "true" : "false") << endl;
288 o << indent << "EBC assumed: " << (ebc_ ? "true" : "false") << endl;
289 switch(abs_method_) {
290 case LinearR12::ABS_ABS :
291 o << indent << "ABS method variant: ABS (Klopper and Samson)" << endl;
292 break;
293 case LinearR12::ABS_ABSPlus :
294 o << indent << "ABS method variant: ABS+ (Klopper and Samson using the union of OBS and ABS for RI)" << endl;
295 break;
296 case LinearR12::ABS_CABS :
297 o << indent << "ABS method variant: CABS (Valeev)" << endl;
298 break;
299 case LinearR12::ABS_CABSPlus :
300 o << indent << "ABS method variant: CABS+ (Valeev using the union of OBS and ABS for RI)" << endl;
301 break;
302 }
303 switch (stdapprox_) {
304 case LinearR12::StdApprox_A :
305 o << indent << "Standard Approximation: A" << endl;
306 break;
307 case LinearR12::StdApprox_Ap :
308 o << indent << "Standard Approximation: A'" << endl;
309 break;
310 case LinearR12::StdApprox_B :
311 o << indent << "Standard Approximation: B" << endl;
312 break;
313 }
314
315 o << indent << "Spin-adapted algorithm: " << (spinadapted_ ? "true" : "false") << endl;
316 if (!vir_basis_->equiv(basis()))
317 o << indent << "Compute MP1 energy: " << (include_mp1_ ? "true" : "false") << endl;
318
319 char* r12ints_str;
320 switch (r12ints_method_) {
321 case R12IntEvalInfo::mem_only:
322 r12ints_str = strdup("mem"); break;
323 case R12IntEvalInfo::mem_posix:
324 r12ints_str = strdup("mem_posix"); break;
325 case R12IntEvalInfo::posix:
326 r12ints_str = strdup("posix"); break;
327#if HAVE_MPIIO
328 case R12IntEvalInfo::mem_mpi:
329 r12ints_str = strdup("mem-mpi"); break;
330 case R12IntEvalInfo::mpi:
331 r12ints_str = strdup("mpi"); break;
332#endif
333 default:
334 throw std::runtime_error("MBPT2_R12::print -- invalid value of r12ints_method_");
335 }
336 o << indent << "How to Store Transformed Integrals: " << r12ints_str << endl << endl;
337 free(r12ints_str);
338 o << indent << "Transformed Integrals file suffix: " << r12ints_file_ << endl << endl;
339 o << indent << "Auxiliary Basis Set (ABS):" << endl;
340 o << incindent; aux_basis_->print(o); o << decindent << endl;
341 o << indent << " Virtuals Basis Set (VBS):" << endl;
342 o << incindent; vir_basis_->print(o); o << decindent << endl;
343 MBPT2::print(o);
344 o << decindent;
345}
346
347RefSymmSCMatrix
348MBPT2_R12::density()
349{
350 ExEnv::out0() << "MBPT2_R12::density() is not implemented" << endl;
351 abort();
352 return 0;
353}
354
355//////////////////////////////////////////////////////////////////////////////
356
357void
358MBPT2_R12::compute()
359{
360 if (std::string(reference_->integral()->class_name())
361 !=integral()->class_name()) {
362 FeatureNotImplemented ex(
363 "cannot use a reference with a different Integral specialization",
364 __FILE__, __LINE__, class_desc());
365 try {
366 ex.elaborate()
367 << "reference uses " << reference_->integral()->class_name()
368 << " but this object uses " << integral()->class_name()
369 << std::endl;
370 }
371 catch (...) {}
372 throw ex;
373 }
374
375 init_variables_();
376 reference_->set_desired_value_accuracy(desired_value_accuracy()
377 / ref_to_mp2r12_acc_);
378
379 compute_energy_a_();
380}
381
382//////////////////////////////////////////////////////////////////////////////
383
384void
385MBPT2_R12::obsolete()
386{
387 r12eval_ = 0;
388 r12a_energy_ = 0;
389 r12ap_energy_ = 0;
390 r12b_energy_ = 0;
391 mp2_corr_energy_ = 0.0;
392 r12_corr_energy_ = 0.0;
393 MBPT2::obsolete();
394}
395
396//////////////////////////////////////////////////////////////////////////////
397
398int
399MBPT2_R12::gradient_implemented() const
400{
401 return 0;
402}
403
404//////////////////////////////////////////////////////////////////////////////
405
406int
407MBPT2_R12::value_implemented() const
408{
409 return 1;
410}
411
412/////////////////////////////////////////////////////////////////////////////
413
414Ref<GaussianBasisSet>
415MBPT2_R12::aux_basis() const
416{
417 return aux_basis_;
418}
419
420/////////////////////////////////////////////////////////////////////////////
421
422Ref<GaussianBasisSet>
423MBPT2_R12::vir_basis() const
424{
425 return vir_basis_;
426}
427
428/////////////////////////////////////////////////////////////////////////////
429
430bool
431MBPT2_R12::gbc() const
432{
433 return gbc_;
434}
435
436/////////////////////////////////////////////////////////////////////////////
437
438bool
439MBPT2_R12::ebc() const
440{
441 return ebc_;
442}
443
444/////////////////////////////////////////////////////////////////////////////
445
446LinearR12::ABSMethod
447MBPT2_R12::abs_method() const
448{
449 return abs_method_;
450}
451
452/////////////////////////////////////////////////////////////////////////////
453
454LinearR12::StandardApproximation
455MBPT2_R12::stdapprox() const
456{
457 return stdapprox_;
458}
459
460/////////////////////////////////////////////////////////////////////////////
461
462bool
463MBPT2_R12::spinadapted() const
464{
465 return spinadapted_;
466}
467
468/////////////////////////////////////////////////////////////////////////////
469
470R12IntEvalInfo::StoreMethod
471MBPT2_R12::r12ints_method() const
472{
473 return r12ints_method_;
474}
475
476/////////////////////////////////////////////////////////////////////////////
477
478const std::string&
479MBPT2_R12::r12ints_file() const
480{
481 return r12ints_file_;
482}
483
484/////////////////////////////////////////////////////////////////////////////
485
486double
487MBPT2_R12::corr_energy()
488{
489 energy();
490 return energy() - ref_energy();
491}
492
493/////////////////////////////////////////////////////////////////////////////
494
495double
496MBPT2_R12::r12_corr_energy()
497{
498 energy();
499 return energy() - mp2_corr_energy_ - ref_energy();
500}
501
502/////////////////////////////////////////////////////////////////////////////
503
504void
505MBPT2_R12::init_variables_()
506{
507 MBPT2::init_variables();
508}
509
510/////////////////////////////////////////////////////////////////////////////
511
512void
513MBPT2_R12::check_integral_factory_()
514{
515 // Only IntegralCints can be used at the moment
516 IntegralCints* r12intf = dynamic_cast<IntegralCints*>(integral().pointer());
517 if (!r12intf) {
518 ostringstream errmsg;
519 errmsg << "Integral factory " << (integral().null() ? "null" : integral()->class_name())
520 << " cannot be used in MBPT2_R12 class - try IntegralCints instead" << ends;
521 throw runtime_error(errmsg.str());
522 }
523}
524
525/////////////////////////////////////////////////////////////////////////////
526
527// Local Variables:
528// mode: c++
529// c-file-style: "CLJ"
530// End:
Note: See TracBrowser for help on using the repository browser.