1 //
2 // scf.h --- definition of the SCF abstract base 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 #ifndef _chemistry_qc_scf_scf_h
29 #define _chemistry_qc_scf_scf_h
30 
31 #ifdef __GNUC__
32 #pragma interface
33 #endif
34 
35 #include <util/group/thread.h>
36 
37 #include <math/optimize/scextrap.h>
38 
39 #include <chemistry/qc/basis/tbint.h>
40 #include <chemistry/qc/wfn/accum.h>
41 #include <chemistry/qc/wfn/obwfn.h>
42 
43 namespace sc {
44 
45 // //////////////////////////////////////////////////////////////////////////
46 
47 /** The SCF class is the base for all classes that use a self-consistent
48 field procedure to solve an effective one body problem. */
49 class SCF: public OneBodyWavefunction {
50   protected:
51     int need_vec_;
52     int compute_guess_;
53 
54     int keep_guess_wfn_;
55     Ref<OneBodyWavefunction> guess_wfn_;
56 
57     int always_use_guess_wfn_;
58 
59     Ref<SelfConsistentExtrapolation> extrap_;
60 
61     Ref<AccumH> accumdih_;
62     Ref<AccumH> accumddh_;
63 
64     int maxiter_;
65     int dens_reset_freq_;
66     int reset_occ_;
67     int local_dens_;
68     size_t storage_;
69     int print_all_evals_;
70     int print_occ_evals_;
71 
72     double level_shift_;
73 
74     Ref<MessageGrp> scf_grp_;
75     Ref<ThreadGrp> threadgrp_;
76     int local_;
77 
78     Ref<TwoBodyInt>* tbis_; // a two body integral evaluator for each thread
79     virtual void init_threads();
80     virtual void done_threads();
81 
82     // implement the Compute::compute() function
83     virtual void compute();
84 
85     // calculate the scf vector, returning the accuracy
86     virtual double compute_vector(double&, double enuclear);
87 
88     // return the DIIS error matrices
89     virtual Ref<SCExtrapError> extrap_error();
90 
91     // calculate the scf gradient
92     virtual void compute_gradient(const RefSCVector&);
93 
94     // calculate the scf hessian
95     virtual void compute_hessian(const RefSymmSCMatrix&);
96 
97     // saves state and restart information after every checkpoint_freq()
98     // SCF iterations
99     virtual void savestate_iter(int);
100 
101     // saves state to the given filename
102     virtual void savestate_to_file(const std::string &filename);
103     std::string previous_savestate_file_;
104 
105     // returns the log of the max density element in each shell block
106     signed char * init_pmax(double *);
107 
108     // given a matrix, this will convert the matrix to a local matrix if
109     // it isn't one already, and return that local matrix.  it will also
110     // set the double* to point to the local matrix's data.
111     enum Access { Read, Write, Accum };
112     RefSymmSCMatrix get_local_data(const RefSymmSCMatrix&, double*&, Access);
113 
114     // create the initial scf vector.  either use the eigenvectors in
115     // guess_wfn_, or use a core Hamiltonian guess.  Call this with needv
116     // equal to 0 if you expect to call it twice with the same geometry
117     // (eg. when calling from both set_occupations() and init_vector()).
118     virtual void initial_vector(int needv=1);
119 
120     // given the total number of density and fock matrices, figure out
121     // how much memory that will require and then set the local_dens_
122     // variable accordingly
123     void init_mem(int);
124 
125     void so_density(const RefSymmSCMatrix& d, double occ, int alp=1);
126 
127     // Returns a new'ed allocation vector if it is in the input,
128     // otherwise null.
129     int *read_occ(const Ref<KeyVal> &, const char *name, int nirrep);
130   public:
131     SCF(StateIn&);
132     /** The KeyVal constructor.
133 
134         <dl>
135 
136         <dt><tt>maxiter</tt><dd> This integer specifies the maximum number
137         of SCF iterations.  The default is 40.
138 
139         <dt><tt>density_reset_frequency</tt><dd> This integer specifies how
140         often, in term of SCF iterations, \f$\Delta D\f$ will be reset to
141         \f$D\f$.  The default is 10.
142 
143         <dt><tt>reset_occuptions</tt><dd> Reassign the occupations after
144         each iteration based on the eigenvalues.  This only has an effect
145         for molecules with higher than \f$C_1\f$ symmetry.  The default is
146         false.
147 
148         <dt><tt>level_shift</tt><dd> The default is 0.
149 
150         <dt><tt>extrap</tt><dd> This specifies an object of type
151         SelfConsistentExtrapolation.  The default is a DIIS object.
152 
153         <dt><tt>memory</tt><dd> The amount of memory that each processor
154         may use.  The default is 0 (minimal memory use).
155 
156         <dt><tt>local_density</tt><dd> If this is true, a local copy of the
157         density and \f$G\f$ matrix will be made on all nodes, even if a
158         distributed matrix specialization is used.  The default is true.
159 
160         <dt><tt>guess_wavefunction</tt><dd> This specifies the initial
161         guess for the solution to the SCF equations.  This can be either a
162         OneBodyWavefunction object or the name of file that contains the
163         saved state of a OneBodyWavefunction object.  By default the
164         one-electron hamiltonian will be diagonalized to obtain the initial
165         guess.
166 
167         <dt><tt>keep_guess_wavefunction</tt><dd> The guess wavefunction is
168         normally discarded after it is projected.  Setting this boolean
169         variable to true will cause the guess to be kept.  This is useful
170         when doing frequencies of symmetric molecules by finite
171         displacements, because the wavefunction is lost whenever the
172         molecule is displaced into lower symmetry.
173 
174         <dt><tt>always_use_guess_wavefunction</tt><dd> If the orbitals must
175         be recomputed after they have already been computed once, then the
176         old orbitals are used as the initial guess by default.  However, if
177         this option is true, then the guess wavefunction will be used, if
178         available.  If a guess wavefunction is not available, then a core
179         Hamiltonian guess will be used.  If this option is set to true,
180         then keep_guess_wavefunction should also be set to true.
181 
182         <dt><tt>print_evals</tt><dd>Takes a boolean value.  If true, print
183         all eigenvalues after the SCF procedure converges.  Takes a boolean
184         value.  The default is false.
185 
186         <dt><tt>print_occ_evals</tt><dd>Takes a boolean value.  If true,
187         print the occupied eigenvalues after the SCF procedure converges.
188         The default is false.
189 
190         </dl> */
191     SCF(const Ref<KeyVal>&);
192     ~SCF();
193 
194     void save_data_state(StateOut&);
195 
196     RefSCMatrix oso_eigenvectors();
197     RefDiagSCMatrix eigenvalues();
198 
199     int spin_unrestricted(); // return 0
200 
201     // return the number of AO Fock matrices needed
202     virtual int n_fock_matrices() const =0;
203 
204     // returns the n'th AO Fock matrix
205     virtual RefSymmSCMatrix fock(int) =0;
206 
207     // return the effective MO fock matrix
208     virtual RefSymmSCMatrix effective_fock() =0;
209 
210     virtual double one_body_energy();
211     virtual void two_body_energy(double &ec, double &ex);
212 
213     void symmetry_changed();
214 
215     void obsolete();
216 
217     void print(std::ostream&o=ExEnv::out0()) const;
218 
219   protected:
220     // the following are scratch and are not checkpointed
221     RefSCMatrix oso_scf_vector_;
222     RefSCMatrix oso_scf_vector_beta_; // only used if !spin_restricted
223     RefSymmSCMatrix hcore_;
224 
225     // //////////////////////////////////////////////////////////////////////
226     // pure virtual member functions follow
227 
228     // tries to automagically guess the MO occupations
229     virtual void set_occupations(const RefDiagSCMatrix&) =0;
230 
231     // //////////////////////////////////////////////////////////////////////
232     // do setup for SCF calculation
233     virtual void init_vector() =0;
234     virtual void done_vector() =0;
235 
236     // calculate new density matrices, returns the rms density difference
237     virtual double new_density() =0;
238 
239     // reset density diff matrix and zero out delta G matrix
240     virtual void reset_density() =0;
241 
242     // return the scf electronic energy
243     virtual double scf_energy() =0;
244 
245     // return the DIIS data matrices
246     virtual Ref<SCExtrapData> extrap_data() =0;
247 
248     // form the AO basis fock matrices
249     virtual void ao_fock(double accuracy) =0;
250 
251     // //////////////////////////////////////////////////////////////////////
252     // do setup for gradient calculation
253     virtual void init_gradient() =0;
254     virtual void done_gradient() =0;
255 
256     virtual RefSymmSCMatrix lagrangian() =0;
257     virtual RefSymmSCMatrix gradient_density() =0;
258     virtual void two_body_deriv(double*) =0;
259 
260     // //////////////////////////////////////////////////////////////////////
261     // do setup for hessian calculation
262     virtual void init_hessian() =0;
263     virtual void done_hessian() =0;
264 
265   private:
266     // This experimental function does SVD of Coulomb matrix
267     // to be used in low-rank reconstruction
268     void svd_product_basis();
269 };
270 
271 }
272 
273 #endif
274 
275 // Local Variables:
276 // mode: c++
277 // c-file-style: "ETS"
278 // End:
279