source: ThirdParty/mpqc_open/src/lib/chemistry/qc/scf/osshf.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: 11.4 KB
Line 
1//
2// osshf.cc --- implementation of the open shell singlet Hartree-Fock SCF class
3//
4// Copyright (C) 1997 Limit Point Systems, Inc.
5//
6// Author: Edward Seidl <seidl@janed.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#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <math.h>
33
34#include <util/misc/timer.h>
35#include <util/misc/formio.h>
36#include <util/state/stateio.h>
37
38#include <chemistry/qc/basis/petite.h>
39
40#include <chemistry/qc/scf/osshf.h>
41#include <chemistry/qc/scf/lgbuild.h>
42#include <chemistry/qc/scf/ltbgrad.h>
43
44#include <chemistry/qc/scf/osshftmpl.h>
45
46using namespace std;
47using namespace sc;
48
49///////////////////////////////////////////////////////////////////////////
50// OSSHF
51
52static ClassDesc OSSHF_cd(
53 typeid(OSSHF),"OSSHF",1,"public OSSSCF",
54 0, create<OSSHF>, create<OSSHF>);
55
56OSSHF::OSSHF(StateIn& s) :
57 SavableState(s),
58 OSSSCF(s)
59{
60}
61
62OSSHF::OSSHF(const Ref<KeyVal>& keyval) :
63 OSSSCF(keyval)
64{
65}
66
67OSSHF::~OSSHF()
68{
69}
70
71void
72OSSHF::save_data_state(StateOut& s)
73{
74 OSSSCF::save_data_state(s);
75}
76
77int
78OSSHF::value_implemented() const
79{
80 return 1;
81}
82
83int
84OSSHF::gradient_implemented() const
85{
86 return 1;
87}
88
89void
90OSSHF::print(ostream&o) const
91{
92 OSSSCF::print(o);
93}
94
95//////////////////////////////////////////////////////////////////////////////
96
97void
98OSSHF::ao_fock(double accuracy)
99{
100 Ref<PetiteList> pl = integral()->petite_list(basis());
101
102 // calculate G. First transform cl_dens_diff_ to the AO basis, then
103 // scale the off-diagonal elements by 2.0
104 RefSymmSCMatrix dd = cl_dens_diff_;
105 cl_dens_diff_ = pl->to_AO_basis(dd);
106 cl_dens_diff_->scale(2.0);
107 cl_dens_diff_->scale_diagonal(0.5);
108
109 RefSymmSCMatrix dda = op_densa_diff_;
110 op_densa_diff_ = pl->to_AO_basis(dda);
111 op_densa_diff_->scale(2.0);
112 op_densa_diff_->scale_diagonal(0.5);
113
114 RefSymmSCMatrix ddb = op_densb_diff_;
115 op_densb_diff_ = pl->to_AO_basis(ddb);
116 op_densb_diff_->scale(2.0);
117 op_densb_diff_->scale_diagonal(0.5);
118
119 // now try to figure out the matrix specialization we're dealing with
120 // if we're using Local matrices, then there's just one subblock, or
121 // see if we can convert G and P to local matrices
122 if (local_ || local_dens_) {
123 // grab the data pointers from the G and P matrices
124 double *gmat, *gmata, *gmatb, *pmat, *pmata, *pmatb;
125 RefSymmSCMatrix gtmp = get_local_data(cl_gmat_, gmat, SCF::Accum);
126 RefSymmSCMatrix ptmp = get_local_data(cl_dens_diff_, pmat, SCF::Read);
127 RefSymmSCMatrix gatmp = get_local_data(op_gmata_, gmata, SCF::Accum);
128 RefSymmSCMatrix patmp = get_local_data(op_densa_diff_, pmata, SCF::Read);
129 RefSymmSCMatrix gbtmp = get_local_data(op_gmatb_, gmatb, SCF::Accum);
130 RefSymmSCMatrix pbtmp = get_local_data(op_densb_diff_, pmatb, SCF::Read);
131
132 signed char * pmax = init_pmax(pmat);
133
134// LocalOSSContribution lclc(gmat, pmat, gmata, pmata, gmatb, pmatb);
135// LocalGBuild<LocalOSSContribution>
136// gb(lclc, tbi_, pl, basis(), scf_grp_, pmax,
137// desired_value_accuracy()/100.0);
138// gb.run();
139 int nthread = threadgrp_->nthread();
140 LocalGBuild<LocalOSSContribution> **gblds =
141 new LocalGBuild<LocalOSSContribution>*[nthread];
142 LocalOSSContribution **conts = new LocalOSSContribution*[nthread];
143
144 double **gmatas = new double*[nthread];
145 gmatas[0] = gmata;
146 double **gmatbs = new double*[nthread];
147 gmatbs[0] = gmatb;
148 double **gmats = new double*[nthread];
149 gmats[0] = gmat;
150
151 Ref<GaussianBasisSet> bs = basis();
152 int ntri = i_offset(bs->nbasis());
153
154 double gmat_accuracy = accuracy;
155 if (min_orthog_res() < 1.0) { gmat_accuracy *= min_orthog_res(); }
156
157 int i;
158 for (i=0; i < nthread; i++) {
159 if (i) {
160 gmatas[i] = new double[ntri];
161 memset(gmatas[i], 0, sizeof(double)*ntri);
162 gmatbs[i] = new double[ntri];
163 memset(gmatbs[i], 0, sizeof(double)*ntri);
164 gmats[i] = new double[ntri];
165 memset(gmats[i], 0, sizeof(double)*ntri);
166 }
167 conts[i] = new LocalOSSContribution(gmats[i], pmat,
168 gmatas[i], pmata, gmatbs[i], pmatb);
169 gblds[i] = new LocalGBuild<LocalOSSContribution>(*conts[i], tbis_[i],
170 pl, bs, scf_grp_, pmax, gmat_accuracy, nthread, i
171 );
172
173 threadgrp_->add_thread(i, gblds[i]);
174 }
175
176 tim_enter("start thread");
177 if (threadgrp_->start_threads() < 0) {
178 ExEnv::err0() << indent
179 << "OSSHF: error starting threads" << endl;
180 abort();
181 }
182 tim_exit("start thread");
183
184 tim_enter("stop thread");
185 if (threadgrp_->wait_threads() < 0) {
186 ExEnv::err0() << indent
187 << "OSSHF: error waiting for threads" << endl;
188 abort();
189 }
190 tim_exit("stop thread");
191
192 double tnint=0;
193 for (i=0; i < nthread; i++) {
194 tnint += gblds[i]->tnint;
195
196 if (i) {
197 for (int j=0; j < ntri; j++) {
198 gmata[j] += gmatas[i][j];
199 gmatb[j] += gmatbs[i][j];
200 gmat[j] += gmats[i][j];
201 }
202 delete[] gmatas[i];
203 delete[] gmatbs[i];
204 delete[] gmats[i];
205 }
206
207 delete gblds[i];
208 delete conts[i];
209 }
210
211 delete[] gmatas;
212 delete[] gmatbs;
213 delete[] gmats;
214 delete[] gblds;
215 delete[] conts;
216
217 delete[] pmax;
218
219 // if we're running on multiple processors, then sum the G matrices
220 if (scf_grp_->n() > 1) {
221 scf_grp_->sum(gmat, i_offset(basis()->nbasis()));
222 scf_grp_->sum(gmata, i_offset(basis()->nbasis()));
223 scf_grp_->sum(gmatb, i_offset(basis()->nbasis()));
224 }
225
226 // if we're running on multiple processors, or we don't have local
227 // matrices, then accumulate gtmp back into G
228 if (!local_ || scf_grp_->n() > 1) {
229 cl_gmat_->convert_accumulate(gtmp);
230 op_gmata_->convert_accumulate(gatmp);
231 op_gmatb_->convert_accumulate(gbtmp);
232 }
233 }
234
235 // for now quit
236 else {
237 ExEnv::err0() << indent << "Cannot yet use anything but Local matrices\n";
238 abort();
239 }
240
241 // get rid of AO delta P
242 cl_dens_diff_ = dd;
243 dd = cl_dens_diff_.clone();
244
245 op_densa_diff_ = dda;
246 dda = op_densa_diff_.clone();
247
248 op_densb_diff_ = ddb;
249 ddb = op_densb_diff_.clone();
250
251 // now symmetrize the skeleton G matrix, placing the result in dd
252 RefSymmSCMatrix skel_gmat = cl_gmat_.copy();
253 skel_gmat.scale(1.0/(double)pl->order());
254 pl->symmetrize(skel_gmat,dd);
255
256 skel_gmat = op_gmata_.copy();
257 skel_gmat.scale(1.0/(double)pl->order());
258 pl->symmetrize(skel_gmat,dda);
259
260 skel_gmat = op_gmatb_.copy();
261 skel_gmat.scale(1.0/(double)pl->order());
262 pl->symmetrize(skel_gmat,ddb);
263
264 // F = H+G
265 cl_fock_.result_noupdate().assign(hcore_);
266 cl_fock_.result_noupdate().accumulate(dd);
267
268 // Fa = H+G-Ga
269 op_focka_.result_noupdate().assign(cl_fock_.result_noupdate());
270 dda.scale(-1.0);
271 op_focka_.result_noupdate().accumulate(dda);
272
273 // Fb = H+G-Gb
274 op_fockb_.result_noupdate().assign(cl_fock_.result_noupdate());
275 ddb.scale(-1.0);
276 op_fockb_.result_noupdate().accumulate(ddb);
277
278 dd.assign(0.0);
279 accumddh_->accum(dd);
280 cl_fock_.result_noupdate().accumulate(dd);
281 op_focka_.result_noupdate().accumulate(dd);
282 op_fockb_.result_noupdate().accumulate(dd);
283
284 cl_fock_.computed()=1;
285 op_focka_.computed()=1;
286 op_fockb_.computed()=1;
287}
288
289//////////////////////////////////////////////////////////////////////////////
290
291void
292OSSHF::two_body_energy(double& ec, double& ex)
293{
294 tim_enter("oshf e2");
295 ec = 0.0;
296 ex = 0.0;
297
298 if (local_ || local_dens_) {
299 Ref<PetiteList> pl = integral()->petite_list(basis());
300
301 // grab the data pointers from the G and P matrices
302 double *dpmat;
303 double *sapmat;
304 double *sbpmat;
305 tim_enter("local data");
306 RefSymmSCMatrix adens = alpha_density();
307 RefSymmSCMatrix bdens = beta_density();
308 RefSymmSCMatrix ddens = adens+bdens;
309
310 // 2C+a+b - 2(c+b) = a-b
311 RefSymmSCMatrix sdensa = bdens.copy();
312 sdensa.scale(-2.0);
313 sdensa.accumulate(ddens);
314 dynamic_cast<BlockedSymmSCMatrix*>(sdensa.pointer())->block(osb_)->assign(0.0);
315
316 // 2C+a+b - 2(c+a) = b-a
317 RefSymmSCMatrix sdensb = adens.copy();
318 sdensb.scale(-2.0);
319 sdensb.accumulate(ddens);
320 dynamic_cast<BlockedSymmSCMatrix*>(sdensb.pointer())->block(osa_)->assign(0.0);
321
322 adens=0;
323 bdens=0;
324
325 ddens = pl->to_AO_basis(ddens);
326 sdensa = pl->to_AO_basis(sdensa);
327 sdensb = pl->to_AO_basis(sdensb);
328
329 ddens->scale(2.0);
330 ddens->scale_diagonal(0.5);
331 sdensa->scale(2.0);
332 sdensa->scale_diagonal(0.5);
333 sdensb->scale(2.0);
334 sdensb->scale_diagonal(0.5);
335
336 RefSymmSCMatrix dptmp = get_local_data(ddens, dpmat, SCF::Read);
337 RefSymmSCMatrix saptmp = get_local_data(sdensa, sapmat, SCF::Read);
338 RefSymmSCMatrix sbptmp = get_local_data(sdensb, sbpmat, SCF::Read);
339 tim_exit("local data");
340
341 // initialize the two electron integral classes
342 Ref<TwoBodyInt> tbi = integral()->electron_repulsion();
343 tbi->set_integral_storage(0);
344
345 signed char * pmax = init_pmax(dpmat);
346
347 LocalOSSEnergyContribution lclc(dpmat, sapmat, sbpmat);
348 LocalGBuild<LocalOSSEnergyContribution>
349 gb(lclc, tbi, pl, basis(), scf_grp_, pmax,
350 desired_value_accuracy()/100.0);
351 gb.run();
352
353 delete[] pmax;
354
355 ec = lclc.ec;
356 ex = lclc.ex;
357 }
358
359 // for now quit
360 else {
361 ExEnv::err0() << indent << "Cannot yet use anything but Local matrices\n";
362 abort();
363 }
364 tim_exit("oshf e2");
365}
366
367/////////////////////////////////////////////////////////////////////////////
368
369void
370OSSHF::two_body_deriv(double * tbgrad)
371{
372 Ref<SCElementMaxAbs> m = new SCElementMaxAbs;
373 cl_dens_.element_op(m.pointer());
374 double pmax = m->result();
375 m=0;
376
377 // now try to figure out the matrix specialization we're dealing with.
378 // if we're using Local matrices, then there's just one subblock, or
379 // see if we can convert P to local matrices
380
381 if (local_ || local_dens_) {
382 // grab the data pointers from the P matrices
383 double *pmat, *pmata, *pmatb;
384 RefSymmSCMatrix ptmp = get_local_data(cl_dens_, pmat, SCF::Read);
385 RefSymmSCMatrix patmp = get_local_data(op_densa_, pmata, SCF::Read);
386 RefSymmSCMatrix pbtmp = get_local_data(op_densb_, pmatb, SCF::Read);
387
388 LocalOSSGradContribution l(pmat,pmata,pmatb);
389 Ref<TwoBodyDerivInt> tbi = integral()->electron_repulsion_deriv();
390 Ref<PetiteList> pl = integral()->petite_list();
391 LocalTBGrad<LocalOSSGradContribution> tb(l, tbi, pl, basis(), scf_grp_,
392 tbgrad, pmax, desired_gradient_accuracy());
393 tb.run();
394 scf_grp_->sum(tbgrad,3 * basis()->molecule()->natom());
395 }
396
397 // for now quit
398 else {
399 ExEnv::err0() << indent
400 << "OSSHF::two_body_deriv: can't do gradient yet\n";
401 abort();
402 }
403}
404
405/////////////////////////////////////////////////////////////////////////////
406
407// Local Variables:
408// mode: c++
409// c-file-style: "ETS"
410// End:
Note: See TracBrowser for help on using the repository browser.