source: ThirdParty/mpqc_open/src/lib/chemistry/qc/scf/ossscf.cc@ 482400e

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open 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 482400e 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: 19.2 KB
Line 
1//
2// ossscf.cc --- implementation of the open shell singlet SCF class
3//
4// Copyright (C) 1996 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 <math/scmat/block.h>
39#include <math/scmat/blocked.h>
40#include <math/scmat/local.h>
41
42#include <math/optimize/scextrapmat.h>
43
44#include <chemistry/qc/basis/petite.h>
45
46#include <chemistry/qc/scf/scflocal.h>
47#include <chemistry/qc/scf/scfops.h>
48#include <chemistry/qc/scf/effh.h>
49#include <chemistry/qc/scf/ossscf.h>
50
51using namespace std;
52using namespace sc;
53
54///////////////////////////////////////////////////////////////////////////
55// OSSSCF
56
57static ClassDesc OSSSCF_cd(
58 typeid(OSSSCF),"OSSSCF",1,"public SCF",
59 0, 0, 0);
60
61OSSSCF::OSSSCF(StateIn& s) :
62 SavableState(s),
63 SCF(s),
64 cl_fock_(this),
65 op_focka_(this),
66 op_fockb_(this)
67{
68 cl_fock_.result_noupdate() =
69 basis_matrixkit()->symmmatrix(so_dimension());
70 cl_fock_.restore_state(s);
71 cl_fock_.result_noupdate().restore(s);
72
73 op_focka_.result_noupdate() =
74 basis_matrixkit()->symmmatrix(so_dimension());
75 op_focka_.restore_state(s);
76 op_focka_.result_noupdate().restore(s);
77
78 op_fockb_.result_noupdate() =
79 basis_matrixkit()->symmmatrix(so_dimension());
80 op_fockb_.restore_state(s);
81 op_fockb_.result_noupdate().restore(s);
82
83 s.get(user_occupations_);
84 s.get(tndocc_);
85 s.get(nirrep_);
86 s.get(ndocc_);
87 s.get(osa_);
88 s.get(osb_);
89
90 // now take care of memory stuff
91 init_mem(6);
92}
93
94OSSSCF::OSSSCF(const Ref<KeyVal>& keyval) :
95 SCF(keyval),
96 cl_fock_(this),
97 op_focka_(this),
98 op_fockb_(this)
99{
100 cl_fock_.compute()=0;
101 cl_fock_.computed()=0;
102
103 op_focka_.compute()=0;
104 op_focka_.computed()=0;
105
106 op_fockb_.compute()=0;
107 op_fockb_.computed()=0;
108
109 // calculate the total nuclear charge
110 double Znuc=molecule()->nuclear_charge();
111
112 // check to see if this is to be a charged molecule
113 double charge = keyval->doublevalue("total_charge");
114 int nelectrons = (int)(Znuc-charge+1.0e-4);
115
116 // figure out how many doubly occupied shells there are
117 if (keyval->exists("ndocc")) {
118 tndocc_ = keyval->intvalue("ndocc");
119 } else {
120 tndocc_ = (nelectrons-2)/2;
121 if ((nelectrons-2)%2) {
122 ExEnv::err0() << endl << indent
123 << "OSSSCF::init: Warning, there's a leftover electron.\n"
124 << incindent
125 << indent << "total_charge = " << charge << endl
126 << indent << "total nuclear charge = " << Znuc << endl
127 << indent << "ndocc_ = " << tndocc_ << endl << decindent;
128 }
129 }
130
131 ExEnv::out0() << endl << indent << "OSSSCF::init: total charge = "
132 << Znuc-2*tndocc_-2 << endl << endl;
133
134 nirrep_ = molecule()->point_group()->char_table().ncomp();
135
136 if (nirrep_==1) {
137 ExEnv::err0() << indent << "OSSSCF::init: cannot do C1 symmetry\n";
138 abort();
139 }
140
141 osa_=-1;
142 osb_=-1;
143
144 ndocc_ = read_occ(keyval, "docc", nirrep_);
145 int *nsocc = read_occ(keyval, "socc", nirrep_);
146 if (ndocc_ && nsocc) {
147 user_occupations_=1;
148 for (int i=0; i < nirrep_; i++) {
149 int nsi = nsocc[i];
150 if (nsi && osa_<0)
151 osa_=i;
152 else if (nsi && osb_<0)
153 osb_=i;
154 else if (nsi) {
155 ExEnv::err0() << indent << "OSSSCF::init: too many open shells\n";
156 abort();
157 }
158 }
159 delete[] nsocc;
160 }
161 else if (ndocc_ && !nsocc || !ndocc_ && nsocc) {
162 ExEnv::outn() << "ERROR: OSSSCF: only one of docc and socc specified: "
163 << "give both or none" << endl;
164 abort();
165 }
166 else {
167 ndocc_=0;
168 user_occupations_=0;
169 set_occupations(0);
170 }
171
172 int i;
173 ExEnv::out0() << indent << "docc = [";
174 for (i=0; i < nirrep_; i++)
175 ExEnv::out0() << " " << ndocc_[i];
176 ExEnv::out0() << " ]\n";
177
178 ExEnv::out0() << indent << "socc = [";
179 for (i=0; i < nirrep_; i++)
180 ExEnv::out0() << " " << (i==osa_ || i==osb_) ? 1 : 0;
181 ExEnv::out0() << " ]\n";
182
183 // check to see if this was done in SCF(keyval)
184 if (!keyval->exists("maxiter"))
185 maxiter_ = 200;
186
187 if (!keyval->exists("level_shift"))
188 level_shift_ = 0.25;
189
190 // now take care of memory stuff
191 init_mem(6);
192}
193
194OSSSCF::~OSSSCF()
195{
196 if (ndocc_) {
197 delete[] ndocc_;
198 ndocc_=0;
199 }
200}
201
202void
203OSSSCF::save_data_state(StateOut& s)
204{
205 SCF::save_data_state(s);
206
207 cl_fock_.save_data_state(s);
208 cl_fock_.result_noupdate().save(s);
209
210 op_focka_.save_data_state(s);
211 op_focka_.result_noupdate().save(s);
212
213 op_fockb_.save_data_state(s);
214 op_fockb_.result_noupdate().save(s);
215
216 s.put(user_occupations_);
217 s.put(tndocc_);
218 s.put(nirrep_);
219 s.put(ndocc_,nirrep_);
220 s.put(osa_);
221 s.put(osb_);
222}
223
224double
225OSSSCF::occupation(int ir, int i)
226{
227 if (i < ndocc_[ir])
228 return 2.0;
229 else if ((ir==osa_ || ir==osb_) && (i == ndocc_[ir]))
230 return 1.0;
231 return 0.0;
232}
233
234double
235OSSSCF::alpha_occupation(int ir, int i)
236{
237 if (i < ndocc_[ir] || (ir==osa_ && i==ndocc_[ir]))
238 return 1.0;
239 return 0.0;
240}
241
242double
243OSSSCF::beta_occupation(int ir, int i)
244{
245 if (i < ndocc_[ir] || (ir==osb_ && i==ndocc_[ir]))
246 return 1.0;
247 return 0.0;
248}
249
250int
251OSSSCF::n_fock_matrices() const
252{
253 return 3;
254}
255
256RefSymmSCMatrix
257OSSSCF::fock(int n)
258{
259 if (n > 2) {
260 ExEnv::err0() << indent
261 << "OSSSCF::fock: there are only three fock matrices, "
262 << scprintf("but fock(%d) was requested\n", n);
263 abort();
264 }
265
266 if (n==0)
267 return cl_fock_.result();
268 else if (n==1)
269 return op_focka_.result();
270 else
271 return op_fockb_.result();
272}
273
274int
275OSSSCF::spin_polarized()
276{
277 return 1;
278}
279
280void
281OSSSCF::print(ostream&o) const
282{
283 int i;
284
285 SCF::print(o);
286 o << indent << "OSSSCF Parameters:\n" << incindent
287 << indent << "ndocc = " << tndocc_ << endl
288 << indent << "docc = [";
289 for (i=0; i < nirrep_; i++)
290 o << " " << ndocc_[i];
291 o << " ]" << endl;
292
293 o << indent << "socc = [";
294 for (i=0; i < nirrep_; i++)
295 o << " " << (i==osa_ || i==osb_) ? 1 : 0;
296 o << " ]" << endl << decindent << endl;
297}
298
299//////////////////////////////////////////////////////////////////////////////
300
301void
302OSSSCF::set_occupations(const RefDiagSCMatrix& ev)
303{
304 if (user_occupations_)
305 return;
306
307 int i,j;
308
309 RefDiagSCMatrix evals;
310
311 if (ev.null()) {
312 initial_vector(0);
313 evals = eigenvalues_.result_noupdate();
314 }
315 else
316 evals = ev;
317
318 // first convert evals to something we can deal with easily
319 BlockedDiagSCMatrix *evalsb = require_dynamic_cast<BlockedDiagSCMatrix*>(evals,
320 "OSSSCF::set_occupations");
321
322 double **vals = new double*[nirrep_];
323 for (i=0; i < nirrep_; i++) {
324 int nf=oso_dimension()->blocks()->size(i);
325 if (nf) {
326 vals[i] = new double[nf];
327 evalsb->block(i)->convert(vals[i]);
328 } else {
329 vals[i] = 0;
330 }
331 }
332
333 // now loop to find the tndocc_ lowest eigenvalues and populate those
334 // MO's
335 int *newdocc = new int[nirrep_];
336 memset(newdocc,0,sizeof(int)*nirrep_);
337
338 for (i=0; i < tndocc_; i++) {
339 // find lowest eigenvalue
340 int lir=0,ln=0;
341 double lowest=999999999;
342
343 for (int ir=0; ir < nirrep_; ir++) {
344 int nf=oso_dimension()->blocks()->size(ir);
345 if (!nf)
346 continue;
347 for (j=0; j < nf; j++) {
348 if (vals[ir][j] < lowest) {
349 lowest=vals[ir][j];
350 lir=ir;
351 ln=j;
352 }
353 }
354 }
355 vals[lir][ln]=999999999;
356 newdocc[lir]++;
357 }
358
359 int osa=-1, osb=-1;
360
361 for (i=0; i < 2; i++) {
362 // find lowest eigenvalue
363 int lir=0,ln=0;
364 double lowest=999999999;
365
366 for (int ir=0; ir < nirrep_; ir++) {
367 int nf=oso_dimension()->blocks()->size(ir);
368 if (!nf)
369 continue;
370 for (j=0; j < nf; j++) {
371 if (vals[ir][j] < lowest) {
372 lowest=vals[ir][j];
373 lir=ir;
374 ln=j;
375 }
376 }
377 }
378 vals[lir][ln]=999999999;
379
380 if (!i) {
381 osa=lir;
382 } else {
383 if (lir==osa) {
384 i--;
385 continue;
386 }
387 osb=lir;
388 }
389 }
390
391 // get rid of vals
392 for (i=0; i < nirrep_; i++)
393 if (vals[i])
394 delete[] vals[i];
395 delete[] vals;
396
397 if (!ndocc_) {
398 ndocc_=newdocc;
399 osa_=osa;
400 osb_=osb;
401 } else {
402 // test to see if newocc is different from ndocc_
403 for (i=0; i < nirrep_; i++) {
404 if (ndocc_[i] != newdocc[i]) {
405 ExEnv::err0() << indent << "OSSSCF::set_occupations: WARNING!!!!\n"
406 << incindent << indent
407 << scprintf("occupations for irrep %d have changed\n", i+1)
408 << indent
409 << scprintf("ndocc was %d, changed to %d", ndocc_[i], newdocc[i])
410 << endl << decindent;
411 }
412 if ((osa != osa_ && osa != osb_) || (osb != osb_ && osb != osa_)) {
413 ExEnv::err0() << indent << "OSSSCF::set_occupations: WARNING!!!!\n"
414 << incindent << indent
415 << "open shell occupations have changed"
416 << endl << decindent;
417 osa_=osa;
418 osb_=osb;
419 reset_density();
420 }
421 }
422
423 memcpy(ndocc_,newdocc,sizeof(int)*nirrep_);
424
425 delete[] newdocc;
426 }
427}
428
429void
430OSSSCF::symmetry_changed()
431{
432 SCF::symmetry_changed();
433 cl_fock_.result_noupdate()=0;
434 op_focka_.result_noupdate()=0;
435 op_fockb_.result_noupdate()=0;
436 nirrep_ = molecule()->point_group()->char_table().ncomp();
437 set_occupations(0);
438}
439
440//////////////////////////////////////////////////////////////////////////////
441//
442// scf things
443//
444
445void
446OSSSCF::init_vector()
447{
448 init_threads();
449
450 // allocate storage for other temp matrices
451 cl_dens_ = hcore_.clone();
452 cl_dens_.assign(0.0);
453
454 cl_dens_diff_ = hcore_.clone();
455 cl_dens_diff_.assign(0.0);
456
457 op_densa_ = hcore_.clone();
458 op_densa_.assign(0.0);
459
460 op_densa_diff_ = hcore_.clone();
461 op_densa_diff_.assign(0.0);
462
463 op_densb_ = hcore_.clone();
464 op_densb_.assign(0.0);
465
466 op_densb_diff_ = hcore_.clone();
467 op_densb_diff_.assign(0.0);
468
469 // gmat is in AO basis
470 cl_gmat_ = basis()->matrixkit()->symmmatrix(basis()->basisdim());
471 cl_gmat_.assign(0.0);
472
473 op_gmata_ = cl_gmat_.clone();
474 op_gmata_.assign(0.0);
475
476 op_gmatb_ = cl_gmat_.clone();
477 op_gmatb_.assign(0.0);
478
479 // test to see if we need a guess vector.
480 if (cl_fock_.result_noupdate().null()) {
481 cl_fock_ = hcore_.clone();
482 cl_fock_.result_noupdate().assign(0.0);
483 op_focka_ = hcore_.clone();
484 op_focka_.result_noupdate().assign(0.0);
485 op_fockb_ = hcore_.clone();
486 op_fockb_.result_noupdate().assign(0.0);
487 }
488
489 // set up trial vector
490 initial_vector(1);
491
492 oso_scf_vector_ = oso_eigenvectors_.result_noupdate();
493}
494
495void
496OSSSCF::done_vector()
497{
498 done_threads();
499
500 cl_gmat_ = 0;
501 cl_dens_ = 0;
502 cl_dens_diff_ = 0;
503 op_gmata_ = 0;
504 op_densa_ = 0;
505 op_densa_diff_ = 0;
506 op_gmatb_ = 0;
507 op_densb_ = 0;
508 op_densb_diff_ = 0;
509
510 oso_scf_vector_ = 0;
511}
512
513RefSymmSCMatrix
514OSSSCF::density()
515{
516 if (!density_.computed()) {
517 RefSymmSCMatrix dens(so_dimension(), basis_matrixkit());
518 RefSymmSCMatrix dens1(so_dimension(), basis_matrixkit());
519 so_density(dens, 2.0);
520 dens.scale(2.0);
521
522 so_density(dens1, 1.0);
523 dens.accumulate(dens1);
524 dens1=0;
525
526 density_ = dens;
527 // only flag the density as computed if the calc is converged
528 if (!value_needed()) density_.computed() = 1;
529 }
530
531 return density_.result_noupdate();
532}
533
534RefSymmSCMatrix
535OSSSCF::alpha_density()
536{
537 RefSymmSCMatrix dens1(so_dimension(), basis_matrixkit());
538 RefSymmSCMatrix dens2(so_dimension(), basis_matrixkit());
539
540 so_density(dens1, 2.0);
541 so_density(dens2, 1.0);
542 dynamic_cast<BlockedSymmSCMatrix*>(dens2.pointer())->block(osb_)->assign(0.0);
543
544 dens1.accumulate(dens2);
545 dens2=0;
546
547 return dens1;
548}
549
550RefSymmSCMatrix
551OSSSCF::beta_density()
552{
553 RefSymmSCMatrix dens1(so_dimension(), basis_matrixkit());
554 RefSymmSCMatrix dens2(so_dimension(), basis_matrixkit());
555
556 so_density(dens1, 2.0);
557 so_density(dens2, 1.0);
558 dynamic_cast<BlockedSymmSCMatrix*>(dens2.pointer())->block(osa_)->assign(0.0);
559
560 dens1.accumulate(dens2);
561 dens2=0;
562
563 return dens1;
564}
565
566void
567OSSSCF::reset_density()
568{
569 cl_gmat_.assign(0.0);
570 cl_dens_diff_.assign(cl_dens_);
571
572 op_gmata_.assign(0.0);
573 op_densa_diff_.assign(op_densa_);
574
575 op_gmatb_.assign(0.0);
576 op_densb_diff_.assign(op_densb_);
577}
578
579double
580OSSSCF::new_density()
581{
582 // copy current density into density diff and scale by -1. later we'll
583 // add the new density to this to get the density difference.
584 cl_dens_diff_.assign(cl_dens_);
585 cl_dens_diff_.scale(-1.0);
586
587 op_densa_diff_.assign(op_densa_);
588 op_densa_diff_.scale(-1.0);
589
590 op_densb_diff_.assign(op_densb_);
591 op_densb_diff_.scale(-1.0);
592
593 so_density(cl_dens_, 2.0);
594 cl_dens_.scale(2.0);
595
596 so_density(op_densa_, 1.0);
597
598 cl_dens_.accumulate(op_densa_);
599
600 op_densb_.assign(op_densa_);
601 dynamic_cast<BlockedSymmSCMatrix*>(op_densa_.pointer())->block(osb_)->assign(0.0);
602 dynamic_cast<BlockedSymmSCMatrix*>(op_densb_.pointer())->block(osa_)->assign(0.0);
603
604 cl_dens_diff_.accumulate(cl_dens_);
605 op_densa_diff_.accumulate(op_densa_);
606 op_densb_diff_.accumulate(op_densb_);
607
608 Ref<SCElementScalarProduct> sp(new SCElementScalarProduct);
609 cl_dens_diff_.element_op(sp.pointer(), cl_dens_diff_);
610
611 double delta = sp->result();
612 delta = sqrt(delta/i_offset(cl_dens_diff_.n()));
613
614 return delta;
615}
616
617double
618OSSSCF::scf_energy()
619{
620 RefSymmSCMatrix t = cl_fock_.result_noupdate().copy();
621 t.accumulate(hcore_);
622
623 RefSymmSCMatrix ga = op_focka_.result_noupdate().copy();
624 ga.scale(-1.0);
625 ga.accumulate(cl_fock_.result_noupdate());
626
627 RefSymmSCMatrix gb = op_fockb_.result_noupdate().copy();
628 gb.scale(-1.0);
629 gb.accumulate(cl_fock_.result_noupdate());
630
631 SCFEnergy *eop = new SCFEnergy;
632 eop->reference();
633 Ref<SCElementOp2> op = eop;
634 t.element_op(op, cl_dens_);
635
636 double cl_e = eop->result();
637
638 eop->reset();
639 ga.element_op(op, op_densa_);
640 double opa_e = eop->result();
641
642 eop->reset();
643 gb.element_op(op, op_densb_);
644 double opb_e = eop->result();
645
646 op=0;
647 eop->dereference();
648 delete eop;
649
650 return cl_e-opa_e-opb_e;
651}
652
653////////////////////////////////////////////////////////////////////////////
654
655Ref<SCExtrapData>
656OSSSCF::extrap_data()
657{
658 RefSymmSCMatrix *m = new RefSymmSCMatrix[3];
659 m[0] = cl_fock_.result_noupdate();
660 m[1] = op_focka_.result_noupdate();
661 m[2] = op_fockb_.result_noupdate();
662
663 Ref<SCExtrapData> data = new SymmSCMatrixNSCExtrapData(3, m);
664 delete[] m;
665
666 return data;
667}
668
669RefSymmSCMatrix
670OSSSCF::effective_fock()
671{
672 // use fock() instead of cl_fock_ just in case this is called from
673 // someplace outside SCF::compute_vector()
674 RefSymmSCMatrix mofock(oso_dimension(), basis_matrixkit());
675 mofock.assign(0.0);
676
677 RefSymmSCMatrix mofocka(oso_dimension(), basis_matrixkit());
678 mofocka.assign(0.0);
679
680 RefSymmSCMatrix mofockb(oso_dimension(), basis_matrixkit());
681 mofockb.assign(0.0);
682
683 // use eigenvectors if oso_scf_vector_ is null
684 RefSCMatrix vec;
685 if (oso_scf_vector_.null()) {
686 vec = eigenvectors();
687 } else {
688 vec = so_to_orthog_so().t() * oso_scf_vector_;
689 }
690
691 mofock.accumulate_transform(vec, fock(0),
692 SCMatrix::TransposeTransform);
693 mofocka.accumulate_transform(vec, fock(1),
694 SCMatrix::TransposeTransform);
695 mofockb.accumulate_transform(vec, fock(2),
696 SCMatrix::TransposeTransform);
697
698 dynamic_cast<BlockedSymmSCMatrix*>(mofocka.pointer())->block(osb_)->assign(0.0);
699 dynamic_cast<BlockedSymmSCMatrix*>(mofockb.pointer())->block(osa_)->assign(0.0);
700
701 mofocka.accumulate(mofockb);
702 mofockb=0;
703
704 Ref<SCElementOp2> op = new GSGeneralEffH(this);
705 mofock.element_op(op, mofocka);
706
707 return mofock;
708}
709
710/////////////////////////////////////////////////////////////////////////////
711
712void
713OSSSCF::init_gradient()
714{
715 // presumably the eigenvectors have already been computed by the time
716 // we get here
717 oso_scf_vector_ = oso_eigenvectors_.result_noupdate();
718}
719
720void
721OSSSCF::done_gradient()
722{
723 cl_dens_=0;
724 op_densa_=0;
725 op_densb_=0;
726 oso_scf_vector_ = 0;
727}
728
729/////////////////////////////////////////////////////////////////////////////
730
731// MO lagrangian
732// c o v
733// c |2*FC|2*FC|0|
734// -------------
735// o |2*FC| FO |0|
736// -------------
737// v | 0 | 0 |0|
738//
739RefSymmSCMatrix
740OSSSCF::lagrangian()
741{
742 RefSCMatrix vec = so_to_orthog_so().t() * oso_scf_vector_;
743
744 RefSymmSCMatrix mofock(oso_dimension(), basis_matrixkit());
745 mofock.assign(0.0);
746 mofock.accumulate_transform(vec, cl_fock_.result_noupdate(),
747 SCMatrix::TransposeTransform);
748
749 RefSymmSCMatrix mofocka(oso_dimension(), basis_matrixkit());
750 mofocka.assign(0.0);
751 mofocka.accumulate_transform(vec, op_focka_.result_noupdate(),
752 SCMatrix::TransposeTransform);
753
754 RefSymmSCMatrix mofockb(oso_dimension(), basis_matrixkit());
755 mofockb.assign(0.0);
756 mofockb.accumulate_transform(vec, op_fockb_.result_noupdate(),
757 SCMatrix::TransposeTransform);
758
759 dynamic_cast<BlockedSymmSCMatrix*>(mofocka.pointer())->block(osb_)->assign(0.0);
760 dynamic_cast<BlockedSymmSCMatrix*>(mofockb.pointer())->block(osa_)->assign(0.0);
761
762 mofocka.accumulate(mofockb);
763 mofockb=0;
764
765 mofock.scale(2.0);
766
767 Ref<SCElementOp2> op = new MOLagrangian(this);
768 mofock.element_op(op, mofocka);
769 mofocka=0;
770
771 // transform MO lagrangian to SO basis
772 RefSymmSCMatrix so_lag(so_dimension(), basis_matrixkit());
773 so_lag.assign(0.0);
774 so_lag.accumulate_transform(vec, mofock);
775
776 // and then from SO to AO
777 Ref<PetiteList> pl = integral()->petite_list();
778 RefSymmSCMatrix ao_lag = pl->to_AO_basis(so_lag);
779
780 ao_lag.scale(-1.0);
781
782 return ao_lag;
783}
784
785RefSymmSCMatrix
786OSSSCF::gradient_density()
787{
788 cl_dens_ = basis_matrixkit()->symmmatrix(so_dimension());
789 op_densa_ = cl_dens_.clone();
790 op_densb_ = cl_dens_.clone();
791
792 so_density(cl_dens_, 2.0);
793 cl_dens_.scale(2.0);
794
795 so_density(op_densa_, 1.0);
796 op_densb_.assign(op_densa_);
797
798 dynamic_cast<BlockedSymmSCMatrix*>(op_densa_.pointer())->block(osb_)->assign(0.0);
799 dynamic_cast<BlockedSymmSCMatrix*>(op_densb_.pointer())->block(osa_)->assign(0.0);
800
801 Ref<PetiteList> pl = integral()->petite_list(basis());
802
803 cl_dens_ = pl->to_AO_basis(cl_dens_);
804 op_densa_ = pl->to_AO_basis(op_densa_);
805 op_densb_ = pl->to_AO_basis(op_densb_);
806
807 RefSymmSCMatrix tdens = cl_dens_.copy();
808 tdens.accumulate(op_densa_);
809 tdens.accumulate(op_densb_);
810
811 op_densa_.scale(2.0);
812 op_densb_.scale(2.0);
813
814 return tdens;
815}
816
817/////////////////////////////////////////////////////////////////////////////
818
819void
820OSSSCF::init_hessian()
821{
822}
823
824void
825OSSSCF::done_hessian()
826{
827}
828
829/////////////////////////////////////////////////////////////////////////////
830
831// Local Variables:
832// mode: c++
833// c-file-style: "ETS"
834// End:
Note: See TracBrowser for help on using the repository browser.