source: ThirdParty/mpqc_open/src/lib/chemistry/qc/wfn/hcorewfn.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: 8.1 KB
Line 
1//
2// hcorewfn.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
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 <util/misc/formio.h>
29#include <util/state/stateio.h>
30
31#include <math/scmat/blocked.h>
32
33#include <chemistry/qc/wfn/obwfn.h>
34#include <chemistry/qc/basis/integral.h>
35#include <chemistry/qc/basis/petite.h>
36
37using namespace std;
38using namespace sc;
39
40/////////////////////////////////////////////////////////////////////////
41
42static ClassDesc HCoreWfn_cd(
43 typeid(HCoreWfn),"HCoreWfn",1,"public OneBodyWavefunction",
44 0, create<HCoreWfn>, create<HCoreWfn>);
45
46HCoreWfn::HCoreWfn(StateIn& s) :
47 SavableState(s),
48 OneBodyWavefunction(s)
49{
50 s.get(nirrep_);
51 s.get(docc_);
52 s.get(socc_);
53 s.get(user_occ_);
54 s.get(total_charge_);
55}
56
57HCoreWfn::HCoreWfn(const Ref<KeyVal>&keyval):
58 OneBodyWavefunction(keyval)
59{
60 CharacterTable ct = molecule()->point_group()->char_table();
61
62 nirrep_ = ct.ncomp();
63 docc_ = new int[nirrep_];
64 socc_ = new int[nirrep_];
65
66 user_occ_ = 0;
67 total_charge_ = keyval->intvalue("total_charge");
68
69 int nuclear_charge = int(molecule()->nuclear_charge());
70 int computed_charge = nuclear_charge;
71
72 for (int i=0; i < nirrep_; i++) {
73 docc_[i]=0;
74 socc_[i]=0;
75
76 if (keyval->exists("docc",i)) {
77 docc_[i] = keyval->intvalue("docc",i);
78 computed_charge -= 2;
79 user_occ_ = 1;
80 }
81 if (keyval->exists("socc",i)) {
82 socc_[i] = keyval->intvalue("socc",i);
83 computed_charge -= 1;
84 user_occ_ = 1;
85 }
86 }
87 if (!keyval->exists("total_charge")) {
88 if (user_occ_) total_charge_ = computed_charge;
89 else total_charge_ = 0;
90 }
91 else if (total_charge_ != computed_charge && user_occ_) {
92 ExEnv::err0() << indent
93 << "ERROR: HCoreWfn: total_charge != computed_charge"
94 << endl;
95 abort();
96 }
97 if (total_charge_ > nuclear_charge) {
98 ExEnv::err0() << indent
99 << "ERROR: HCoreWfn: total_charge > nuclear_charge"
100 << endl;
101 abort();
102 }
103}
104
105HCoreWfn::~HCoreWfn()
106{
107 delete[] docc_;
108 delete[] socc_;
109}
110
111void
112HCoreWfn::save_data_state(StateOut&s)
113{
114 OneBodyWavefunction::save_data_state(s);
115 s.put(nirrep_);
116 s.put(docc_,nirrep_);
117 s.put(socc_,nirrep_);
118 s.put(user_occ_);
119 s.put(total_charge_);
120}
121
122RefSCMatrix
123HCoreWfn::oso_eigenvectors()
124{
125 if (!oso_eigenvectors_.computed() || !eigenvalues_.computed()) {
126 RefSymmSCMatrix hcore_oso(oso_dimension(), basis_matrixkit());
127 hcore_oso->assign(0.0);
128 hcore_oso->accumulate_transform(so_to_orthog_so(), core_hamiltonian());
129
130 if (debug_ > 1) {
131 core_hamiltonian().print("hcore in SO basis");
132 }
133
134 if (debug_ > 1) {
135 hcore_oso.print("hcore in ortho SO basis");
136 }
137
138 RefSCMatrix vec(oso_dimension(), oso_dimension(), basis_matrixkit());
139 RefDiagSCMatrix val(oso_dimension(), basis_matrixkit());
140
141 hcore_oso.diagonalize(val,vec);
142
143 if (debug_ > 1) {
144 val.print("hcore eigenvalues in ortho SO basis");
145 vec.print("hcore eigenvectors in ortho SO basis");
146 }
147 oso_eigenvectors_=vec;
148 oso_eigenvectors_.computed() = 1;
149
150 eigenvalues_ = val;
151 eigenvalues_.computed() = 1;
152
153 if (!user_occ_) {
154 int nelectron = int(molecule()->nuclear_charge()) - total_charge_;
155 int ndocc = nelectron/2;
156 int nsocc = nelectron%2;
157 fill_occ(val, ndocc, docc_, nsocc, socc_);
158
159 ExEnv::out0() << indent << "docc = [";
160 for (int i=0; i<nirrep_; i++) ExEnv::out0() << " " << docc_[i];
161 ExEnv::out0() << "]" << endl;
162
163 ExEnv::out0() << indent << "socc = [";
164 for (int i=0; i<nirrep_; i++) ExEnv::out0() << " " << socc_[i];
165 ExEnv::out0() << "]" << endl;
166 }
167 }
168
169 return oso_eigenvectors_.result_noupdate();
170}
171
172RefDiagSCMatrix
173HCoreWfn::eigenvalues()
174{
175 if (!eigenvalues_.computed()) {
176 oso_eigenvectors();
177 }
178
179 return eigenvalues_.result_noupdate();
180}
181
182RefSymmSCMatrix
183HCoreWfn::density()
184{
185 if (!density_.computed()) {
186 // Make sure the eigenvectors are computed before
187 // the MO density is computed, otherwise, docc and
188 // socc might not have been initialized.
189 oso_eigenvectors();
190
191 RefDiagSCMatrix mo_density(oso_dimension(), basis_matrixkit());
192 BlockedDiagSCMatrix *modens
193 = dynamic_cast<BlockedDiagSCMatrix*>(mo_density.pointer());
194 if (!modens) {
195 ExEnv::err0() << indent
196 << "HCoreWfn::density: wrong MO matrix kit" << endl;
197 abort();
198 }
199
200 modens->assign(0.0);
201 for (int iblock=0; iblock < modens->nblocks(); iblock++) {
202 RefDiagSCMatrix modens_ib = modens->block(iblock);
203 int i;
204 for (i=0; i < docc_[iblock]; i++)
205 modens_ib->set_element(i, 2.0);
206 for ( ; i < docc_[iblock]+socc_[iblock]; i++)
207 modens_ib->set_element(i, 1.0);
208 }
209
210 RefSymmSCMatrix dens(so_dimension(), basis_matrixkit());
211 dens->assign(0.0);
212 dens->accumulate_transform(so_to_orthog_so().t() * mo_to_orthog_so(),
213 mo_density);
214
215 if (debug_ > 1) {
216 mo_density.print("MO Density");
217 dens.print("SO Density");
218 ExEnv::out0()
219 << indent << "Nelectron(MO) = " << mo_density.trace()
220 << endl
221 << indent << "Nelectron(SO) = "
222 << (overlap()*dens).trace()
223 << endl;
224 }
225
226 density_ = dens;
227 density_.computed() = 1;
228 }
229
230 return density_.result_noupdate();
231}
232
233double
234HCoreWfn::occupation(int ir, int i)
235{
236 if (i < docc_[ir])
237 return 2.0;
238 else if (i < docc_[ir]+socc_[ir])
239 return 1.0;
240 else
241 return 0.0;
242}
243
244int
245HCoreWfn::spin_polarized()
246{
247 return 0;
248}
249
250int
251HCoreWfn::spin_unrestricted()
252{
253 return 0;
254}
255
256void
257HCoreWfn::compute()
258{
259 double e = (density()*core_hamiltonian()).trace();
260 set_energy(e);
261 set_actual_value_accuracy(desired_value_accuracy());
262 return;
263}
264
265int
266HCoreWfn::value_implemented() const
267{
268 return 1;
269}
270
271void
272HCoreWfn::fill_occ(const RefDiagSCMatrix &evals,int ndocc,int *docc,
273 int nsocc, int *socc)
274{
275 BlockedDiagSCMatrix *bval
276 = require_dynamic_cast<BlockedDiagSCMatrix*>(evals.pointer(),
277 "HCoreWave: getting occupations");
278 int nblock = bval->nblocks();
279 if (nblock != nirrep_) {
280 ExEnv::errn() << "ERROR: HCoreWfn: fill_occ: nblock != nirrep" << endl
281 << " nblock = " << nblock << endl
282 << " nirrep = " << nirrep_ << endl;
283 abort();
284 }
285 memset(docc,0,sizeof(docc[0])*nblock);
286 memset(socc,0,sizeof(socc[0])*nblock);
287 for (int i=0; i<ndocc; i++) {
288 double lowest;
289 int lowest_j = -1;
290 for (int j=0; j<nblock; j++) {
291 RefDiagSCMatrix block = bval->block(j);
292 if (block.null()) continue;
293 double current = block->get_element(docc[j]);
294 if (lowest_j < 0 || lowest > current) {
295 lowest = current;
296 lowest_j = j;
297 }
298 }
299 docc[lowest_j]++;
300 }
301 for (int i=0; i<nsocc; i++) {
302 double lowest;
303 int lowest_j = -1;
304 for (int j=0; j<nblock; j++) {
305 double current = bval->block(j)->get_element(docc[j]+socc[j]);
306 if (lowest_j < 0 || lowest > current) {
307 lowest = current;
308 lowest_j = j;
309 }
310 }
311 socc[lowest_j]++;
312 }
313}
314
315/////////////////////////////////////////////////////////////////////////////
316
317// Local Variables:
318// mode: c++
319// c-file-style: "ETS"
320// End:
Note: See TracBrowser for help on using the repository browser.