source: ThirdParty/mpqc_open/src/lib/chemistry/qc/psi/psiwfn.cc

Candidate_v1.6.1
Last change on this file 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: 11.8 KB
Line 
1
2#ifdef __GNUC__
3#pragma implementation
4#endif
5
6#include <stdexcept>
7#include <math.h>
8
9#include <util/keyval/keyval.h>
10#include <util/misc/formio.h>
11#include <util/state/stateio.h>
12#include <math/scmat/matrix.h>
13#include <math/symmetry/pointgrp.h>
14#include <chemistry/molecule/molecule.h>
15#include <chemistry/qc/psi/psiwfn.h>
16
17using namespace std;
18
19namespace sc {
20
21//////////////////////////////////////////////////////////////////////////
22
23static ClassDesc PsiWavefunction_cd(
24 typeid(PsiWavefunction),"PsiWavefunction",2,"public Wavefunction",
25 0, 0, 0);
26
27PsiWavefunction::PsiWavefunction(const Ref<KeyVal>&keyval):
28 Wavefunction(keyval)
29{
30 exenv_ << keyval->describedclassvalue("psienv");
31 if (exenv_.null()) {
32 ExEnv::err0() << "PsiWavefunction::PsiWavefunction: no Psi execution environment object (psienv)" << endl;
33 abort();
34 }
35
36 nirrep_ = molecule()->point_group()->char_table().order();
37 docc_ = read_occ(keyval,"docc",nirrep_);
38 socc_ = read_occ(keyval,"socc",nirrep_);
39 frozen_docc_ = read_occ(keyval,"frozen_docc",nirrep_);
40 frozen_uocc_ = read_occ(keyval,"frozen_uocc",nirrep_);
41
42 int bytes = keyval->intvalue("memory");
43 if (bytes <= 2000000)
44 bytes = 2000000;
45 int bytes_str_len = (int)ceil(log10((long double)bytes));
46 memory_ = new char[bytes_str_len+5];
47 sprintf(memory_,"(%ld B)",bytes);
48}
49
50PsiWavefunction::~PsiWavefunction()
51{
52}
53
54PsiWavefunction::PsiWavefunction(StateIn&s):
55 SavableState(s),
56 Wavefunction(s)
57{
58 throw std::runtime_error("PsiWavefunction::PsiWavefunction(StateIn&) -- cannot restore state of Psi wave functions");
59}
60
61void
62PsiWavefunction::save_data_state(StateOut&s)
63{
64 throw std::runtime_error("PsiWavefunction::save_data_state -- cannot save state of Psi wave functions, set savestate = no in your input file");
65}
66
67void
68PsiWavefunction::print(ostream&o) const
69{
70 Wavefunction::print(o);
71 exenv_->print(o);
72}
73
74void
75PsiWavefunction::compute()
76{
77 if (gradient_needed() && !gradient_implemented()) {
78 ExEnv::out0() << scprintf("Gradient is not implemented for this Psi wavefunction") << endl;
79 abort();
80 }
81 double energy_acc = desired_value_accuracy();
82 double grad_acc = desired_gradient_accuracy();
83 if (energy_acc > 1.0e-6) energy_acc = 1.0e-6;
84 if (grad_acc > 1.0e-7) grad_acc = 1.0e-7;
85 if (gradient_needed() && energy_acc > grad_acc/10.0)
86 energy_acc = grad_acc/10.0;
87
88 write_input((int)-log10(energy_acc));
89 exenv_->run_psi();
90
91 // read output
92 if (gradient_needed()) {
93 Ref<PsiFile11> file11 = exenv_->get_psi_file11();
94 file11->open();
95
96 set_energy(file11->get_energy(0));
97 set_actual_value_accuracy(energy_acc);
98
99 int natom_mpqc = molecule()->natom();
100 int natom = file11->get_natom(0);
101 if (natom != natom_mpqc) {
102 ExEnv::out0() << scprintf("Number of atoms in MPQC and Psi3 do not match") << endl;
103 abort();
104 }
105 RefSCVector gradientvec = basis()->matrixkit()->vector(moldim());
106 for(int atom=0; atom<natom; atom++) {
107 gradientvec[3*atom] = file11->get_grad(0,atom,0);
108 gradientvec[3*atom+1] = file11->get_grad(0,atom,1);
109 gradientvec[3*atom+2] = file11->get_grad(0,atom,2);
110 }
111 set_gradient(gradientvec);
112 file11->close();
113 file11->remove();
114 }
115 else {
116 double energy = 0.0;;
117 set_energy(energy);
118 set_actual_value_accuracy(energy_acc);
119 }
120}
121
122RefSymmSCMatrix
123PsiWavefunction::density()
124{
125 abort();
126 return 0;
127}
128
129int
130PsiWavefunction::nelectron()
131{
132 abort();
133 return 0;
134}
135
136void
137PsiWavefunction::write_basic_input(int conv)
138{
139 const char *dertype = gradient_needed() ? "first" : "none";
140
141 Ref<PsiInput> psiinput = get_psi_input();
142 psiinput->write_defaults(exenv_,dertype);
143 psiinput->write_keyword("psi:memory",memory_);
144 psiinput->begin_section("input");
145 psiinput->write_keyword("no_reorient","true");
146 psiinput->write_keyword("keep_ref_frame","true");
147 psiinput->write_basis(basis());
148 if (basis()->max_nfunction_in_shell() != basis()->max_ncartesian_in_shell())
149 psiinput->write_keyword("puream","true");
150 psiinput->write_geom(molecule());
151 psiinput->end_section();
152 psiinput->write_basis_sets(basis());
153}
154
155// Shamelessly borrowed from class SCF
156int *
157PsiWavefunction::read_occ(const Ref<KeyVal> &keyval, const char *name, int nirrep)
158{
159 int *occ = 0;
160 if (keyval->exists(name)) {
161 if (keyval->count(name) != nirrep) {
162 ExEnv::err0() << indent
163 << "ERROR: PsiWavefunction: have " << nirrep << " irreps but "
164 << name << " vector is length " << keyval->count(name)
165 << endl;
166 abort();
167 }
168 occ = new int[nirrep];
169 for (int i=0; i<nirrep; i++) {
170 occ[i] = keyval->intvalue(name,i);
171 }
172 }
173 return occ;
174}
175
176//////////////////////////////////////////////////////////////////////////
177
178static ClassDesc PsiSCF_cd(
179 typeid(PsiSCF),"PsiSCF",1,"public PsiWavefunction",
180 0, 0, 0);
181
182PsiSCF::PsiSCF(const Ref<KeyVal>&keyval):
183 PsiWavefunction(keyval)
184{
185 if (!docc_ || !socc_) {
186 if (keyval->exists("total_charge") && keyval->exists("multiplicity")) {
187 charge_ = keyval->intvalue("total_charge");
188 multp_ = keyval->intvalue("multiplicity");
189 if (multp_ < 1) {
190 ExEnv::err0() << indent
191 << "ERROR: PsiSCF: valid multiplicity has to be >= 1" << endl;
192 abort();
193 }
194 }
195 else {
196 ExEnv::err0() << indent
197 << "ERROR: PsiSCF: multiplicity and total_charge need "
198 << "to be specified when docc (socc) are missing" << endl;
199 abort();
200 }
201 }
202}
203
204PsiSCF::~PsiSCF()
205{
206}
207
208PsiSCF::PsiSCF(StateIn&s):
209 PsiWavefunction(s)
210{
211}
212
213void
214PsiSCF::save_data_state(StateOut&s)
215{
216 PsiWavefunction::save_data_state(s);
217}
218
219//////////////////////////////////////////////////////////////////////////
220
221static ClassDesc PsiCLHF_cd(
222 typeid(PsiCLHF),"PsiCLHF",1,"public PsiSCF",
223 0, create<PsiCLHF>, create<PsiCLHF>);
224
225PsiCLHF::PsiCLHF(const Ref<KeyVal>&keyval):
226 PsiSCF(keyval)
227{
228 if (!docc_ && multp_ != 1) {
229 ExEnv::err0() << indent
230 << "ERROR: PsiCLHF: multiplicity should be 1 for CLHF wave function" << endl;
231 abort();
232 }
233}
234
235PsiCLHF::~PsiCLHF()
236{
237}
238
239PsiCLHF::PsiCLHF(StateIn&s):
240 PsiSCF(s)
241{
242}
243
244void
245PsiCLHF::write_basic_input(int convergence)
246{
247 Ref<PsiInput> input = get_psi_input();
248 input->write_keyword("psi:reference","rhf");
249 if (docc_)
250 input->write_keyword_array("psi:docc",nirrep_,docc_);
251 else {
252 input->write_keyword("psi:multp",multp_);
253 input->write_keyword("psi:charge",charge_);
254 }
255}
256
257void
258PsiCLHF::write_input(int convergence)
259{
260 Ref<PsiInput> input = get_psi_input();
261 input->open();
262 PsiWavefunction::write_basic_input(convergence);
263 write_basic_input(convergence);
264 input->write_keyword("psi:wfn","scf");
265 input->close();
266}
267
268//////////////////////////////////////////////////////////////////////////
269
270static ClassDesc PsiHSOSHF_cd(
271 typeid(PsiHSOSHF),"PsiHSOSHF",1,"public PsiSCF",
272 0, create<PsiHSOSHF>, create<PsiHSOSHF>);
273
274PsiHSOSHF::PsiHSOSHF(const Ref<KeyVal>&keyval):
275 PsiSCF(keyval)
276{
277 if ((!docc_ || !socc_) && multp_ == 1) {
278 ExEnv::err0() << indent
279 << "ERROR: PsiHSOSHF: multiplicity should be > 1 for HSOSHF wave function" << endl;
280 abort();
281 }
282}
283
284PsiHSOSHF::~PsiHSOSHF()
285{
286}
287
288PsiHSOSHF::PsiHSOSHF(StateIn&s):
289 PsiSCF(s)
290{
291}
292
293void
294PsiHSOSHF::write_basic_input(int convergence)
295{
296 Ref<PsiInput> input = get_psi_input();
297 input->write_keyword("psi:reference","rohf");
298 if (docc_)
299 input->write_keyword_array("psi:docc",nirrep_,docc_);
300 if (socc_)
301 input->write_keyword_array("psi:socc",nirrep_,socc_);
302}
303
304void
305PsiHSOSHF::write_input(int convergence)
306{
307 Ref<PsiInput> input = get_psi_input();
308 input->open();
309 PsiWavefunction::write_basic_input(convergence);
310 write_basic_input(convergence);
311 input->write_keyword("psi:wfn","scf");
312 input->close();
313}
314
315
316//////////////////////////////////////////////////////////////////////////
317
318static ClassDesc PsiUHF_cd(
319 typeid(PsiUHF),"PsiUHF",1,"public PsiSCF",
320 0, create<PsiUHF>, create<PsiUHF>);
321
322PsiUHF::PsiUHF(const Ref<KeyVal>&keyval):
323 PsiSCF(keyval)
324{
325}
326
327PsiUHF::~PsiUHF()
328{
329}
330
331PsiUHF::PsiUHF(StateIn&s):
332 PsiSCF(s)
333{
334}
335
336void
337PsiUHF::write_basic_input(int convergence)
338{
339 Ref<PsiInput> input = get_psi_input();
340 input->write_keyword("psi:reference","uhf");
341 if (docc_)
342 input->write_keyword_array("psi:docc",nirrep_,docc_);
343 if (socc_)
344 input->write_keyword_array("psi:socc",nirrep_,socc_);
345}
346
347void
348PsiUHF::write_input(int convergence)
349{
350 Ref<PsiInput> input = get_psi_input();
351 input->open();
352 PsiWavefunction::write_basic_input(convergence);
353 write_basic_input(convergence);
354 input->write_keyword("psi:wfn","scf");
355 input->close();
356}
357
358//////////////////////////////////////////////////////////////////////////
359
360static ClassDesc PsiCCSD_cd(
361 typeid(PsiCCSD),"PsiCCSD",1,"public PsiWavefunction",
362 0, create<PsiCCSD>, create<PsiCCSD>);
363
364PsiCCSD::PsiCCSD(const Ref<KeyVal>&keyval):
365 PsiWavefunction(keyval)
366{
367 reference_ << keyval->describedclassvalue("reference");
368 if (reference_.null()) {
369 ExEnv::err0() << "PsiCCSD::PsiCCSD: no reference wavefunction" << endl;
370 abort();
371 }
372}
373
374PsiCCSD::~PsiCCSD()
375{
376}
377
378PsiCCSD::PsiCCSD(StateIn&s):
379 PsiWavefunction(s)
380{
381 reference_ << SavableState::restore_state(s);
382}
383
384int
385PsiCCSD::gradient_implemented() const
386{
387 int impl = 0;
388 PsiSCF::RefType reftype = reference_->reftype();
389 if (reftype == PsiSCF::rhf || reftype == PsiSCF::hsoshf)
390 impl = 1;
391 return impl;
392}
393
394void
395PsiCCSD::save_data_state(StateOut&s)
396{
397 PsiWavefunction::save_data_state(s);
398 SavableState::save_state(reference_.pointer(),s);
399}
400
401void
402PsiCCSD::write_input(int convergence)
403{
404 if (gradient_needed())
405 reference_->do_gradient(1);
406 else
407 reference_->do_gradient(0);
408
409 Ref<PsiInput> input = get_psi_input();
410 input->open();
411 PsiWavefunction::write_basic_input(convergence);
412 reference_->write_basic_input(convergence);
413 input->write_keyword("psi:wfn","ccsd");
414 if (frozen_docc_)
415 input->write_keyword_array("psi:frozen_docc",nirrep_,frozen_docc_);
416 if (frozen_uocc_)
417 input->write_keyword_array("psi:frozen_uocc",nirrep_,frozen_uocc_);
418 input->close();
419}
420
421//////////////////////////////////////////////////////////////////////////
422
423static ClassDesc PsiCCSD_T_cd(
424 typeid(PsiCCSD_T),"PsiCCSD_T",1,"public PsiWavefunction",
425 0, create<PsiCCSD_T>, create<PsiCCSD_T>);
426
427PsiCCSD_T::PsiCCSD_T(const Ref<KeyVal>&keyval):
428 PsiWavefunction(keyval)
429{
430 reference_ << keyval->describedclassvalue("reference");
431 if (reference_.null()) {
432 ExEnv::err0() << "PsiCCSD_T::PsiCCSD_T: no reference wavefunction" << endl;
433 abort();
434 }
435
436 PsiSCF::RefType reftype = reference_->reftype();
437 if (reftype == PsiSCF::hsoshf) {
438 ExEnv::err0() << "PsiCCSD_T::PsiCCSD_T: HSOSHF-based CCSD(T) has not been implemented yet" << endl;
439 abort();
440 }
441}
442
443PsiCCSD_T::~PsiCCSD_T()
444{
445}
446
447PsiCCSD_T::PsiCCSD_T(StateIn&s):
448 PsiWavefunction(s)
449{
450 reference_ << SavableState::restore_state(s);
451}
452
453int
454PsiCCSD_T::gradient_implemented() const
455{
456 int impl = 0;
457 PsiSCF::RefType reftype = reference_->reftype();
458 return impl;
459}
460
461void
462PsiCCSD_T::save_data_state(StateOut&s)
463{
464 PsiWavefunction::save_data_state(s);
465 SavableState::save_state(reference_.pointer(),s);
466}
467
468void
469PsiCCSD_T::write_input(int convergence)
470{
471 if (gradient_needed())
472 reference_->do_gradient(1);
473 else
474 reference_->do_gradient(0);
475
476 Ref<PsiInput> input = get_psi_input();
477 input->open();
478 PsiWavefunction::write_basic_input(convergence);
479 reference_->write_basic_input(convergence);
480 input->write_keyword("psi:wfn","ccsd");
481 input->begin_section("psi");
482 input->write_keyword("exec","(\"cints\" \"cscf\" \"transqt\" \"ccsort\" \"ccenergy\" \"cchbar\" \"cctriples\")");
483 input->end_section();
484 if (frozen_docc_)
485 input->write_keyword_array("psi:frozen_docc",nirrep_,frozen_docc_);
486 if (frozen_uocc_)
487 input->write_keyword_array("psi:frozen_uocc",nirrep_,frozen_uocc_);
488 input->close();
489}
490
491//////////////////////////////////////////////////////////////////////////
492
493}
494
495// Local Variables:
496// mode: c++
497// c-file-style: "CLJ"
498// End:
Note: See TracBrowser for help on using the repository browser.