source: ThirdParty/mpqc_open/src/lib/chemistry/qc/scf/tchf.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: 12.1 KB
Line 
1//
2// tchf.cc --- implementation of the two-configuration 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/tchf.h>
41#include <chemistry/qc/scf/lgbuild.h>
42#include <chemistry/qc/scf/ltbgrad.h>
43
44#include <chemistry/qc/scf/tchftmpl.h>
45
46using namespace std;
47using namespace sc;
48
49///////////////////////////////////////////////////////////////////////////
50// TCHF
51
52static ClassDesc TCHF_cd(
53 typeid(TCHF),"TCHF",1,"public TCSCF",
54 0, create<TCHF>, create<TCHF>);
55
56TCHF::TCHF(StateIn& s) :
57 SavableState(s),
58 TCSCF(s)
59{
60}
61
62TCHF::TCHF(const Ref<KeyVal>& keyval) :
63 TCSCF(keyval)
64{
65}
66
67TCHF::~TCHF()
68{
69}
70
71void
72TCHF::save_data_state(StateOut& s)
73{
74 TCSCF::save_data_state(s);
75}
76
77int
78TCHF::value_implemented() const
79{
80 return 1;
81}
82
83int
84TCHF::gradient_implemented() const
85{
86 return 1;
87}
88
89void
90TCHF::print(ostream&o) const
91{
92 TCSCF::print(o);
93}
94
95//////////////////////////////////////////////////////////////////////////////
96
97void
98TCHF::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 da = pl->to_AO_basis(cl_dens_diff_);
105 RefSymmSCMatrix db = da.copy();
106 RefSymmSCMatrix oda = pl->to_AO_basis(op_densa_diff_);
107 RefSymmSCMatrix odb = pl->to_AO_basis(op_densb_diff_);
108 da.accumulate(oda);
109 db.accumulate(odb);
110
111 da->scale(2.0);
112 da->scale_diagonal(0.5);
113
114 db->scale(2.0);
115 db->scale_diagonal(0.5);
116
117 oda->scale(2.0);
118 oda->scale_diagonal(0.5);
119
120 odb->scale(2.0);
121 odb->scale_diagonal(0.5);
122
123 // now try to figure out the matrix specialization we're dealing with
124 // if we're using Local matrices, then there's just one subblock, or
125 // see if we can convert G and P to local matrices
126 if (local_ || local_dens_) {
127
128 // grab the data pointers from the G and P matrices
129 double *gmata, *gmatb, *kmata, *kmatb, *pmata, *pmatb, *opmata, *opmatb;
130 RefSymmSCMatrix gatmp = get_local_data(ao_gmata_, gmata, SCF::Accum);
131 RefSymmSCMatrix patmp = get_local_data(da, pmata, SCF::Read);
132 RefSymmSCMatrix gbtmp = get_local_data(ao_gmatb_, gmatb, SCF::Accum);
133 RefSymmSCMatrix pbtmp = get_local_data(db, pmatb, SCF::Read);
134 RefSymmSCMatrix katmp = get_local_data(ao_ka_, kmata, SCF::Accum);
135 RefSymmSCMatrix opatmp = get_local_data(oda, opmata, SCF::Read);
136 RefSymmSCMatrix kbtmp = get_local_data(ao_kb_, kmatb, SCF::Accum);
137 RefSymmSCMatrix opbtmp = get_local_data(odb, opmatb, SCF::Read);
138
139 signed char * pmax = init_pmax(pmata);
140 signed char * pmaxb = init_pmax(pmatb);
141
142 int i;
143 for (i=0; i < i_offset(basis()->nshell()); i++) {
144 if (pmaxb[i] > pmax[i])
145 pmax[i]=pmaxb[i];
146 }
147
148 delete[] pmaxb;
149
150// LocalTCContribution lclc(gmata, pmata, gmatb, pmatb,
151// kmata, opmata, kmatb, opmatb);
152// LocalGBuild<LocalTCContribution>
153// gb(lclc, tbi_, pl, basis(), scf_grp_, pmax,
154// desired_value_accuracy()/100.0);
155// gb.run();
156 int nthread = threadgrp_->nthread();
157 LocalGBuild<LocalTCContribution> **gblds =
158 new LocalGBuild<LocalTCContribution>*[nthread];
159 LocalTCContribution **conts = new LocalTCContribution*[nthread];
160
161 double **gmatas = new double*[nthread];
162 gmatas[0] = gmata;
163 double **gmatbs = new double*[nthread];
164 gmatbs[0] = gmatb;
165 double **kmatas = new double*[nthread];
166 kmatas[0] = kmata;
167 double **kmatbs = new double*[nthread];
168 kmatbs[0] = kmatb;
169
170 Ref<GaussianBasisSet> bs = basis();
171 int ntri = i_offset(bs->nbasis());
172
173 double gmat_accuracy = accuracy;
174 if (min_orthog_res() < 1.0) { gmat_accuracy *= min_orthog_res(); }
175
176 for (i=0; i < nthread; i++) {
177 if (i) {
178 gmatas[i] = new double[ntri];
179 memset(gmatas[i], 0, sizeof(double)*ntri);
180 gmatbs[i] = new double[ntri];
181 memset(gmatbs[i], 0, sizeof(double)*ntri);
182 kmatas[i] = new double[ntri];
183 memset(kmatas[i], 0, sizeof(double)*ntri);
184 kmatbs[i] = new double[ntri];
185 memset(kmatbs[i], 0, sizeof(double)*ntri);
186 }
187 conts[i] = new LocalTCContribution(gmatas[i], pmata, gmatbs[i], pmatb,
188 kmatas[i], opmata, kmatbs[i], opmatb);
189 gblds[i] = new LocalGBuild<LocalTCContribution>(*conts[i], tbis_[i],
190 pl, bs, scf_grp_, pmax, gmat_accuracy, nthread, i
191 );
192
193 threadgrp_->add_thread(i, gblds[i]);
194 }
195
196 tim_enter("start thread");
197 if (threadgrp_->start_threads() < 0) {
198 ExEnv::err0() << indent
199 << "TCHF: error starting threads" << endl;
200 abort();
201 }
202 tim_exit("start thread");
203
204 tim_enter("stop thread");
205 if (threadgrp_->wait_threads() < 0) {
206 ExEnv::err0() << indent
207 << "TCHF: error waiting for threads" << endl;
208 abort();
209 }
210 tim_exit("stop thread");
211
212 double tnint=0;
213 for (i=0; i < nthread; i++) {
214 tnint += gblds[i]->tnint;
215
216 if (i) {
217 for (int j=0; j < ntri; j++) {
218 gmata[j] += gmatas[i][j];
219 gmatb[j] += gmatbs[i][j];
220 kmata[j] += kmatas[i][j];
221 kmatb[j] += kmatbs[i][j];
222 }
223 delete[] gmatas[i];
224 delete[] gmatbs[i];
225 delete[] kmatas[i];
226 delete[] kmatbs[i];
227 }
228
229 delete gblds[i];
230 delete conts[i];
231 }
232
233 delete[] gmatas;
234 delete[] gmatbs;
235 delete[] kmatas;
236 delete[] kmatbs;
237 delete[] gblds;
238 delete[] conts;
239
240 delete[] pmax;
241
242 // if we're running on multiple processors, then sum the G matrices
243 if (scf_grp_->n() > 1) {
244 scf_grp_->sum(gmata, i_offset(basis()->nbasis()));
245 scf_grp_->sum(gmatb, i_offset(basis()->nbasis()));
246 scf_grp_->sum(kmata, i_offset(basis()->nbasis()));
247 scf_grp_->sum(kmatb, i_offset(basis()->nbasis()));
248 }
249
250 // if we're running on multiple processors, or we don't have local
251 // matrices, then accumulate gtmp back into G
252 if (!local_ || scf_grp_->n() > 1) {
253 ao_gmata_->convert_accumulate(gatmp);
254 ao_gmatb_->convert_accumulate(gbtmp);
255 ao_ka_->convert_accumulate(katmp);
256 ao_kb_->convert_accumulate(kbtmp);
257 }
258 }
259
260 // for now quit
261 else {
262 ExEnv::err0() << indent << "Cannot yet use anything but Local matrices\n";
263 abort();
264 }
265
266 da=0;
267 db=0;
268 oda=0;
269 odb=0;
270
271 // now symmetrize the skeleton G matrix, placing the result in dd
272 RefSymmSCMatrix skel_gmat = ao_gmata_.copy();
273 skel_gmat.scale(1.0/(double)pl->order());
274 pl->symmetrize(skel_gmat,focka_.result_noupdate());
275
276 skel_gmat = ao_gmatb_.copy();
277 skel_gmat.scale(1.0/(double)pl->order());
278 pl->symmetrize(skel_gmat,fockb_.result_noupdate());
279
280 skel_gmat = ao_ka_.copy();
281 skel_gmat.scale(1.0/(double)pl->order());
282 pl->symmetrize(skel_gmat,ka_.result_noupdate());
283
284 skel_gmat = ao_kb_.copy();
285 skel_gmat.scale(1.0/(double)pl->order());
286 pl->symmetrize(skel_gmat,kb_.result_noupdate());
287
288 // Fa = H+Ga
289 focka_.result_noupdate().accumulate(hcore_);
290
291 // Fb = H+Gb
292 fockb_.result_noupdate().accumulate(hcore_);
293
294 RefSymmSCMatrix ddh = hcore_.clone();
295 ddh.assign(0.0);
296 accumddh_->accum(ddh);
297 focka_.result_noupdate().accumulate(ddh);
298 fockb_.result_noupdate().accumulate(ddh);
299 ka_.result_noupdate().accumulate(ddh);
300 kb_.result_noupdate().accumulate(ddh);
301 ddh=0;
302
303 focka_.computed()=1;
304 fockb_.computed()=1;
305 ka_.computed()=1;
306 kb_.computed()=1;
307}
308
309/////////////////////////////////////////////////////////////////////////////
310
311void
312TCHF::two_body_energy(double &ec, double &ex)
313{
314 ExEnv::err0() << indent
315 << "TCHF:two_body_energy not implemented"
316 << endl;
317 abort();
318
319 tim_enter("tchf e2");
320 ec = 0.0;
321 ex = 0.0;
322
323 if (local_ || local_dens_) {
324 Ref<PetiteList> pl = integral()->petite_list(basis());
325
326 // grab the data pointers from the G and P matrices
327 double *pmata, *pmatb, *spmata, *spmatb;
328
329 tim_enter("local data");
330 RefSymmSCMatrix densa = alpha_density();
331 RefSymmSCMatrix densb = beta_density();
332 RefSymmSCMatrix densc = densb.clone();
333 so_density(densc, 2.0);
334 densc.scale(-2.0);
335
336 RefSymmSCMatrix sdensa = densa.copy();
337 sdensa.accumulate(densc);
338
339 RefSymmSCMatrix sdensb = densb.copy();
340 sdensb.accumulate(densc);
341
342 densc=0;
343
344 densa = pl->to_AO_basis(densa);
345 densb = pl->to_AO_basis(densb);
346 sdensa = pl->to_AO_basis(sdensa);
347 sdensb = pl->to_AO_basis(sdensb);
348
349 densa->scale(2.0);
350 densa->scale_diagonal(0.5);
351 densb->scale(2.0);
352 densb->scale_diagonal(0.5);
353 sdensa->scale(2.0);
354 sdensa->scale_diagonal(0.5);
355 sdensb->scale(2.0);
356 sdensb->scale_diagonal(0.5);
357
358 RefSymmSCMatrix ptmpa = get_local_data(densa, pmata, SCF::Read);
359 RefSymmSCMatrix ptmpb = get_local_data(densb, pmatb, SCF::Read);
360 RefSymmSCMatrix sptmpa = get_local_data(sdensa, spmata, SCF::Read);
361 RefSymmSCMatrix sptmpb = get_local_data(sdensb, spmatb, SCF::Read);
362 tim_exit("local data");
363
364 // initialize the two electron integral classes
365 Ref<TwoBodyInt> tbi = integral()->electron_repulsion();
366 tbi->set_integral_storage(0);
367
368 tim_enter("init pmax");
369 signed char * pmax = init_pmax(pmata);
370 tim_exit("init pmax");
371
372 LocalTCEnergyContribution lclc(pmata,pmatb,spmata,spmatb);
373 LocalGBuild<LocalTCEnergyContribution>
374 gb(lclc, tbi, pl, basis(), scf_grp_, pmax,
375 desired_value_accuracy()/100.0);
376 gb.run();
377
378 delete[] pmax;
379
380 printf("%20.10f %20.10f\n", lclc.eca, lclc.exa);
381 printf("%20.10f %20.10f\n", lclc.ecb, lclc.exb);
382 printf("%20.10f %20.10f\n", lclc.ecab, lclc.exab);
383
384 }
385 else {
386 ExEnv::err0() << indent << "Cannot yet use anything but Local matrices\n";
387 abort();
388 }
389 tim_exit("tchf e2");
390}
391
392/////////////////////////////////////////////////////////////////////////////
393
394void
395TCHF::two_body_deriv(double * tbgrad)
396{
397 Ref<SCElementMaxAbs> m = new SCElementMaxAbs;
398 cl_dens_.element_op(m.pointer());
399 double pmax = m->result();
400 m=0;
401
402 // now try to figure out the matrix specialization we're dealing with.
403 // if we're using Local matrices, then there's just one subblock, or
404 // see if we can convert P to local matrices
405
406 if (local_ || local_dens_) {
407 // grab the data pointers from the P matrices
408 double *pmat, *pmata, *pmatb;
409 RefSymmSCMatrix ptmp = get_local_data(cl_dens_, pmat, SCF::Read);
410 RefSymmSCMatrix patmp = get_local_data(op_densa_, pmata, SCF::Read);
411 RefSymmSCMatrix pbtmp = get_local_data(op_densb_, pmatb, SCF::Read);
412
413 LocalTCGradContribution l(pmat,pmata,pmatb,ci1_,ci2_);
414 Ref<TwoBodyDerivInt> tbi = integral()->electron_repulsion_deriv();
415 Ref<PetiteList> pl = integral()->petite_list();
416 LocalTBGrad<LocalTCGradContribution> tb(l, tbi, pl, basis(), scf_grp_,
417 tbgrad, pmax, desired_gradient_accuracy());
418 tb.run();
419 scf_grp_->sum(tbgrad,3 * basis()->molecule()->natom());
420 }
421
422 // for now quit
423 else {
424 ExEnv::err0() << indent
425 << "TCHF::two_body_deriv: can't do gradient yet\n";
426 abort();
427 }
428}
429
430/////////////////////////////////////////////////////////////////////////////
431
432// Local Variables:
433// mode: c++
434// c-file-style: "ETS"
435// End:
Note: See TracBrowser for help on using the repository browser.