source: ThirdParty/mpqc_open/src/lib/chemistry/qc/wfn/eht.cc@ b7e5b0

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 b7e5b0 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: 10.1 KB
Line 
1//
2// eht.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/eht.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 ExtendedHuckelWfn_cd(
43 typeid(ExtendedHuckelWfn),"ExtendedHuckelWfn",1,"public OneBodyWavefunction",
44 0, create<ExtendedHuckelWfn>, create<ExtendedHuckelWfn>);
45
46ExtendedHuckelWfn::ExtendedHuckelWfn(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
57ExtendedHuckelWfn::ExtendedHuckelWfn(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*docc_[i];
79 user_occ_ = 1;
80 }
81 if (keyval->exists("socc",i)) {
82 socc_[i] = keyval->intvalue("socc",i);
83 computed_charge -= 1*socc_[i];
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: ExtendedHuckelWfn: total_charge != computed_charge"
94 << endl;
95 abort();
96 }
97 if (total_charge_ > nuclear_charge) {
98 ExEnv::err0() << indent
99 << "ERROR: ExtendedHuckelWfn: total_charge > nuclear_charge"
100 << endl;
101 abort();
102 }
103}
104
105ExtendedHuckelWfn::~ExtendedHuckelWfn()
106{
107 delete[] docc_;
108 delete[] socc_;
109}
110
111void
112ExtendedHuckelWfn::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
122RefSymmSCMatrix
123ExtendedHuckelWfn::h_eht_oso()
124{
125 Ref<PetiteList> pl = integral()->petite_list();
126
127 // Compute H in the AO basis
128 double K = 1.75;
129 Ref<AtomInfo> atominfo = molecule()->atominfo();
130 RefSymmSCMatrix h_ao = pl->to_AO_basis(overlap());
131 int natom = basis()->ncenter();
132 int funcoff1 = 0;
133 for (int atom1=0; atom1<natom; atom1++) {
134 int nbasis1 = basis()->nbasis_on_center(atom1);
135 double I1 = atominfo->ip(molecule()->Z(atom1));
136 int funcoff2 = 0;
137 for (int atom2=0; atom2<=atom1; atom2++) {
138 int nbasis2 = basis()->nbasis_on_center(atom2);
139 double I2 = atominfo->ip(molecule()->Z(atom2));
140 for (int func1=0; func1<nbasis1; func1++) {
141 if (atom1 == atom2) nbasis2 = func1 + 1;
142 for (int func2=0; func2<nbasis2; func2++) {
143 int i1 = funcoff1+func1;
144 int i2 = funcoff2+func2;
145 double val = h_ao(i1,i2);
146 if (atom1 == atom2 && func1 == func2) {
147 // The overlap integral is not a part of the diagonal
148 // element in standard EHT formulae. It is here though,
149 // since basis functions are not always normalized (some
150 // d shell components for example).
151 val *= -I1;
152 }
153 else {
154 val *= -0.5*K*(I1+I2);
155 }
156 h_ao(i1,i2) = val;
157 }
158 }
159 funcoff2 += nbasis2;
160 }
161 funcoff1 += nbasis1;
162 }
163
164 if (debug_ > 1) h_ao.print("h in the AO basis");
165
166 // Compute H in the SO basis
167 RefSymmSCMatrix h_so = pl->to_SO_basis(h_ao);
168
169 if (debug_ > 1) {
170 pl->to_AO_basis(overlap()).print("S in AO basis");
171 overlap().print("S in SO basis");
172 pl->aotoso().print("AO to SO transform");
173 h_so.print("h in the SO basis");
174 }
175
176 // Compute H in the OSO basis
177 RefSymmSCMatrix h_oso(oso_dimension(), basis_matrixkit());
178 h_oso->assign(0.0);
179 h_oso->accumulate_transform(so_to_orthog_so(),h_so);
180
181 return h_oso;
182}
183
184RefSCMatrix
185ExtendedHuckelWfn::oso_eigenvectors()
186{
187 if (!oso_eigenvectors_.computed() || !eigenvalues_.computed()) {
188 RefSymmSCMatrix h_oso = h_eht_oso();
189
190 if (debug_ > 1) {
191 h_oso.print("h in ortho SO basis");
192 }
193
194 RefSCMatrix vec(oso_dimension(), oso_dimension(), basis_matrixkit());
195 RefDiagSCMatrix val(oso_dimension(), basis_matrixkit());
196
197 h_oso.diagonalize(val,vec);
198
199 if (debug_ > 1) {
200 val.print("h eigenvalues in ortho SO basis");
201 vec.print("h eigenvectors in ortho SO basis");
202 }
203 oso_eigenvectors_=vec;
204 oso_eigenvectors_.computed() = 1;
205
206 eigenvalues_ = val;
207 eigenvalues_.computed() = 1;
208
209 if (!user_occ_) {
210 int nelectron = int(molecule()->nuclear_charge()) - total_charge_;
211 int ndocc = nelectron/2;
212 int nsocc = nelectron%2;
213 fill_occ(val, ndocc, docc_, nsocc, socc_);
214
215 ExEnv::out0() << indent << "docc = [";
216 for (int i=0; i<nirrep_; i++) ExEnv::out0() << " " << docc_[i];
217 ExEnv::out0() << "]" << endl;
218
219 ExEnv::out0() << indent << "socc = [";
220 for (int i=0; i<nirrep_; i++) ExEnv::out0() << " " << socc_[i];
221 ExEnv::out0() << "]" << endl;
222 }
223 }
224
225 return oso_eigenvectors_.result_noupdate();
226}
227
228RefDiagSCMatrix
229ExtendedHuckelWfn::eigenvalues()
230{
231 if (!eigenvalues_.computed()) {
232 oso_eigenvectors();
233 }
234
235 return eigenvalues_.result_noupdate();
236}
237
238RefSymmSCMatrix
239ExtendedHuckelWfn::density()
240{
241 if (!density_.computed()) {
242 // Make sure the eigenvectors are computed before
243 // the MO density is computed, otherwise, docc and
244 // socc might not have been initialized.
245 oso_eigenvectors();
246
247 RefDiagSCMatrix mo_density(oso_dimension(), basis_matrixkit());
248 BlockedDiagSCMatrix *modens
249 = dynamic_cast<BlockedDiagSCMatrix*>(mo_density.pointer());
250 if (!modens) {
251 ExEnv::err0() << indent
252 << "ExtendedHuckelWfn::density: wrong MO matrix kit" << endl;
253 abort();
254 }
255
256 modens->assign(0.0);
257 for (int iblock=0; iblock < modens->nblocks(); iblock++) {
258 RefDiagSCMatrix modens_ib = modens->block(iblock);
259 int i;
260 for (i=0; i < docc_[iblock]; i++)
261 modens_ib->set_element(i, 2.0);
262 for ( ; i < docc_[iblock]+socc_[iblock]; i++)
263 modens_ib->set_element(i, 1.0);
264 }
265
266 if (debug_ > 1) mo_density.print("MO Density");
267
268 RefSymmSCMatrix dens(so_dimension(), basis_matrixkit());
269 dens->assign(0.0);
270 dens->accumulate_transform(so_to_orthog_so().t() * mo_to_orthog_so(),
271 mo_density);
272
273 if (debug_ > 1) {
274 mo_density.print("MO Density");
275 dens.print("SO Density");
276 ExEnv::out0()
277 << indent << "Nelectron(MO) = " << mo_density.trace()
278 << endl
279 << indent << "Nelectron(SO) = "
280 << (overlap()*dens).trace()
281 << endl;
282 }
283
284 density_ = dens;
285 density_.computed() = 1;
286 }
287
288 return density_.result_noupdate();
289}
290
291double
292ExtendedHuckelWfn::occupation(int ir, int i)
293{
294 if (i < docc_[ir])
295 return 2.0;
296 else if (i < docc_[ir]+socc_[ir])
297 return 1.0;
298 else
299 return 0.0;
300}
301
302int
303ExtendedHuckelWfn::spin_polarized()
304{
305 return 0;
306}
307
308int
309ExtendedHuckelWfn::spin_unrestricted()
310{
311 return 0;
312}
313
314void
315ExtendedHuckelWfn::compute()
316{
317 double e = (density()*core_hamiltonian()).trace();
318 set_energy(e);
319 set_actual_value_accuracy(desired_value_accuracy());
320 return;
321}
322
323int
324ExtendedHuckelWfn::value_implemented() const
325{
326 return 1;
327}
328
329void
330ExtendedHuckelWfn::fill_occ(const RefDiagSCMatrix &evals,int ndocc,int *docc,
331 int nsocc, int *socc)
332{
333 BlockedDiagSCMatrix *bval
334 = require_dynamic_cast<BlockedDiagSCMatrix*>(evals.pointer(),
335 "ExtendedHuckelWfn: getting occupations");
336 int nblock = bval->nblocks();
337 if (nblock != nirrep_) {
338 ExEnv::errn() << "ERROR: ExtendedHuckelWfn: fill_occ: nblock != nirrep" << endl
339 << " nblock = " << nblock << endl
340 << " nirrep = " << nirrep_ << endl;
341 abort();
342 }
343 memset(docc,0,sizeof(docc[0])*nblock);
344 memset(socc,0,sizeof(socc[0])*nblock);
345 for (int i=0; i<ndocc; i++) {
346 double lowest;
347 int lowest_j = -1;
348 for (int j=0; j<nblock; j++) {
349 RefDiagSCMatrix block = bval->block(j);
350 if (block.null()) continue;
351 double current = block->get_element(docc[j]);
352 if (lowest_j < 0 || lowest > current) {
353 lowest = current;
354 lowest_j = j;
355 }
356 }
357 docc[lowest_j]++;
358 }
359 for (int i=0; i<nsocc; i++) {
360 double lowest;
361 int lowest_j = -1;
362 for (int j=0; j<nblock; j++) {
363 double current = bval->block(j)->get_element(docc[j]+socc[j]);
364 if (lowest_j < 0 || lowest > current) {
365 lowest = current;
366 lowest_j = j;
367 }
368 }
369 socc[lowest_j]++;
370 }
371}
372
373/////////////////////////////////////////////////////////////////////////////
374
375// Local Variables:
376// mode: c++
377// c-file-style: "ETS"
378// End:
Note: See TracBrowser for help on using the repository browser.