MADNESS 0.10.1
oep.h
Go to the documentation of this file.
1/*
2 * oep.h
3 *
4 * Created on: Nov 6, 2019
5 * Author: fbischoff
6 */
7
8#ifndef SRC_APPS_CHEM_OEP_H_
9#define SRC_APPS_CHEM_OEP_H_
10
11
12
13#include<madness/chem/nemo.h>
18
19namespace madness {
20
21/// Class to compute terms of the potential
23
24 double thresh_high=1.e-5;
25 double thresh_low=1.e-7;
26 double eps_regularize=1.e-8;
29
33
34 std::size_t get_result_size() const {
35 return 1;
36 }
37
38 /// @param[in] t vector containing: oep, refdensity, longrange
39 /// @return (num1/denom1 - num2/denom2) * mask + (1-mask)*longrange
40 std::vector<Tensor<double> > operator()(const Key<3> & key,
41 const std::vector<Tensor<double> >& t) const {
42
43 const Tensor<double>& refdens=t[0];
44 const Tensor<double>& num1=t[1];
45 const Tensor<double>& denom1=t[2];
46 const Tensor<double>& num2=t[3];
47 const Tensor<double>& denom2=t[4];
48 const Tensor<double>& longrange=t[5];
49
50 // set 1 if above munge interval (dens > thresh_high) or 0 if below munge interval (dens < thresh_low)
51 // interpolate inbetween with logarithmic form of (r - lo)/(hi - lo) because this yields near linear behavior
52 Tensor<double> U = copy(refdens); // copy refdens in oder to have the same dimension in the tensor
53 U.fill(1.0); // start with a fuction that is 1.0 everywhere
55 U,
56 double r = refdens(IND);
57 double result=num1(IND)/(denom1(IND)+eps_regularize)
58 - num2(IND)/(denom2(IND)+eps_regularize);
59 if (square_denominator) result=num1(IND)/(denom1(IND)*denom1(IND)+eps_regularize)
60 - num2(IND)/(denom2(IND)*denom2(IND)+eps_regularize);
61 if (r > thresh_high) {
62 U(IND) = result;
63 } else if (r < thresh_low) {
64 U(IND) = longrange(IND);
65 } else {
66 // mask = 1 if refdens>hi, 0 if refdens < lo, interpolate in between
67 double mask=(log10(refdens(IND)) - log_low)/(log_high - log_low);
68 U(IND)=mask*result + (1.0-mask)*longrange(IND);
69 }
70 );
71 return std::vector<Tensor<double> > (1,U);
72 }
73};
74
75/// TODO:
76/// - change algorithm to handle localized orbitals
77/// - do not recompute the OEP potentials that don't depend on the orbital energies/Fock matrix elements
78/// - do not recompute the HF contributions to the OEP potentials
79/// - think about the long-range part of the Slater potential (or medium-range)
81public:
82 static constexpr char const *tag = "oep";
83
85 initialize<std::vector<std::string> >("model",{"dcep"},"comment on this: oaep ocep dcep mrks");
86 initialize<unsigned int>("maxiter",150,"maximum number of iterations in OEP algorithm");
87 initialize<bool>("restart",false,"restart from previous OEP calculation");
88 initialize<bool>("no_compute",false,"read from previous OEP calculation, no computation");
89 initialize<double>("levelshift",0.0,"shift occupied orbital energies in the BSH operator");
90// initialize<double>("conv_threshold",1.e-5,"comment on this");
91 initialize<double>("density_threshold_high",1.e-6,"comment on this");
92 initialize<double>("density_threshold_low",1.e-8,"comment on this");
93 initialize<double>("density_threshold_inv",1.e-9,"comment on this");
94 initialize<std::vector<double> >("kain_param",{1.0e-8, 3.0},"comment on this");
95
96// std::vector<bool> oep_model = {false, false, false, false};
97 initialize<unsigned int>("saving_amount",0,"choose level 0, 1, 2 or 3 for saving functions");
98 initialize<unsigned int>("save_iter_orbs",0,"if > 0 save all orbitals every ... iterations (needs a lot of storage!");
99 initialize<unsigned int>("save_iter_density",0,"if > 0 save KS density every ... iterations");
100 initialize<unsigned int>("save_iter_IKS",0,"if > 0 save IKS every ... iterations");
101 initialize<unsigned int>("save_iter_kin_tot_KS",0,"if > 0 save kin_tot_KS every ... iterations");
102 initialize<unsigned int>("save_iter_kin_P_KS",0,"if > 0 save kin_P_KS every ... iterations");
103 initialize<unsigned int>("save_iter_corrections",0,"if > 0 save OEP correction(s) every ... iterations");
104 initialize<unsigned int>("save_iter_effective_potential",0,"if > 0 save effective potential every ... iterations");
105 }
106
108 read_input_and_commandline_options(world, parser, "oep");
109 }
110
111 OEP_Parameters(const OEP_Parameters& other) = default;
112
113
114 std::string get_tag() const override {
115 return std::string("oep");
116 }
117
118
120 set_derived_value("density_threshold_high",10.0*cparam.econv());
121 set_derived_value("density_threshold_low",0.01*get<double>("density_threshold_high"));
123 MADNESS_EXCEPTION("confused thresholds for the long-range transition",1);
124 }
125 set_derived_value("density_threshold_inv",0.1*get<double>("density_threshold_low"));
126
127 if (levelshift()>0.0) {
128 print("levelshift > 0.0 in oep parameters\n\n");
129 MADNESS_EXCEPTION("levelshift > 0.0 in oep parameters",1);
130 }
131 }
132
133 // convenience functions
134 std::vector<std::string> model() const {return get<std::vector<std::string> >("model");}
135
136 bool restart() const {return get<bool>("restart");}
137 bool no_compute() const {return get<bool>("no_compute");}
138 unsigned int maxiter() const {return get<unsigned int>("maxiter");}
139 double levelshift() const {return get<double>("levelshift");}
140// double conv_thresh() const {return get<double>("conv_threshold");}
141 double dens_thresh_hi() const {return get<double>("density_threshold_high");}
142 double dens_thresh_lo() const {return get<double>("density_threshold_low");}
143 double dens_thresh_inv() const{return get<double>("density_threshold_inv");}
144 unsigned int saving_amount() const {return get<unsigned int>("saving_amount");}
145 unsigned int save_iter_corrections () const {return get<unsigned int>("save_iter_corrections");}
146
147 std::vector<double> kain_param() const {return get<std::vector<double> >("kain_param");}
148
149};
150
151
152class OEP : public Nemo {
153
154
155protected:
156 /// parameters for this OEP calculation
158
159private:
160 /// the wave function reference that determines the local potential
161 std::shared_ptr<const Nemo> reference;
162
163 /// the final local potential
165
166 /// collection of results
167 std::vector<OEPResults> results;
168
169public:
170
171 OEP(World& world, const OEP_Parameters& oepparam, const std::shared_ptr<const Nemo>& reference)
172 : Nemo(world, reference->get_calc_param(), reference->get_nemo_param(), reference->molecule()), // OEP is a nemo calculation, ctor will set param from reference
173 oep_param(oepparam),
175
176 // add tight convergence criteria
177 std::vector<std::string> convergence_crit=get_calc_param().get<std::vector<std::string> >("convergence_criteria");
178 if (std::find(convergence_crit.begin(),convergence_crit.end(),"each_energy")==convergence_crit.end()) {
179 convergence_crit.push_back("each_energy");
180 }
181 calc->param.set_derived_value("convergence_criteria",convergence_crit);
182
184
185 // check that reference is well converged
186 MADNESS_CHECK_THROW(reference->get_calc_param().converge_each_energy(),"need tightly converged reference for OEP calculation");
187
188 }
189
190
192 : Nemo(world, parser),
193 oep_param(world, parser) {
194
195 // add tight convergence criteria
196 std::vector<std::string> convergence_crit=get_calc_param().get<std::vector<std::string> >("convergence_criteria");
197 if (std::find(convergence_crit.begin(),convergence_crit.end(),"each_energy")==convergence_crit.end()) {
198 convergence_crit.push_back("each_energy");
199 }
200 calc->param.set_derived_value("convergence_criteria",convergence_crit);
201
202 // set reference
203 auto ref=std::make_shared<Nemo>(world,parser);
204 ref->get_calc()->param.set_derived_value("convergence_criteria",convergence_crit);
205 set_reference(ref);
206
208 }
209
210 std::string name() const {return "oep";}
211
212 static void help() {
213 print_header2("help page for oep");
214 print("The oep code computes local exchange potentials based on a Hartree-Fock calculation from nemo");
215 print("oep --print_parameters\n");
216 print("You can perform a simple calculation by running\n");
217 print("oep --geometry=h2o.xyz\n");
218 print("provided you have an xyz file in your directory.");
219
220 }
221
222 static void print_parameters() {
224 print("default parameters for the oep program are");
225 param.print("oep", "end");
226 print("\n\nthe molecular geometry must be specified in a separate block:");
228 }
229
230 void set_reference(const std::shared_ptr<Nemo> reference1) {
231 reference=reference1;
232 }
233
234 std::shared_ptr<const Nemo> get_reference() const {
235 return reference;
236 }
237
238 void print_parameters(std::vector<std::string> what) const {
239 for (auto w : what) {
240 if (w=="oep") oep_param.print("oep");
241 else if (w=="reference") reference->get_calc_param().print("dft");
242 else if (w=="oep_calc") get_calc_param().print("oep_calc");
243 else {MADNESS_EXCEPTION(std::string("unknown parameter set to print "+w).c_str(),1);}
244 }
245 }
246
248 return Vfinal;
249 }
250
251 virtual double value() {
252 return value(calc->molecule.get_all_coords());
253 }
254
255 /// update the json file with calculation input and output
256 void output_calc_info_schema(const double& energy) const;
257
258
259 virtual double value(const Tensor<double>& x) {
260 MADNESS_CHECK_THROW(reference->check_converged(x),"OEP reference is not converged at this geometry");
261 set_protocol(get_calc_param().econv());
262 calc->copy_data(world,*(reference->get_calc()));
263 double energy=0.0;
264 Tensor<double> fock;
266 if (load_mos) load_restartdata(fock);
267
268 if (not oep_param.no_compute()) energy=solve(reference->get_calc()->get_amo());
270 return energy;
271 };
272
273 /// Iterative energy calculation for approximate OEP with EXACT EXCHANGE functional
274 /// for other functionals, slater potential must be modified
275 /// HF orbitals and eigenvalues are used as the guess here
276 /// note that KS_nemo is a reference and changes oep->get_calc()->amo orbitals
277 /// same for orbital energies (eigenvalues) KS_eigvals which is oep->get_calc()->aeps
278 /// converged if norm, total energy difference and orbital energy differences (if not OAEP) are converged
279 double solve(const vecfuncT& HF_nemo);
280
281 /// results are computed in compute_and_print_final_energies
282 nlohmann::json analyze() const override {
283 // turn Results vector into a json object
284 nlohmann::json results_json;
285 for (const auto& r : results) {
286 results_json.push_back(r.to_json());
287 }
288 return results_json;
289 };
290
291 OEPResults iterate(const std::string model, const vecfuncT& HF_nemo, const tensorT& HF_eigvals,
292 vecfuncT& KS_nemo, tensorT& KS_Fock, real_function_3d& Voep,
293 const real_function_3d Vs) const;
294
295 virtual std::shared_ptr<Fock<double,3>> make_fock_operator() const;
296
297// MolecularOrbitals<double,3> to_MO() const {
298// std::vector<std::string> str_irreps;
299// vecfuncT aaa=symmetry_projector(calc->amo,R_square,str_irreps);
300// return MolecularOrbitals<double,3>(aaa,this->get_calc()->aeps,str_irreps,this->get_calc()->aocc,this->get_calc()->aset);
301// }
302
303 void save_restartdata(const Tensor<double>& fock) const;
304
306
307 std::tuple<Tensor<double>, vecfuncT> recompute_HF(const vecfuncT& HF_nemo) const;
308
309 /// The following function tests all essential parts of the OEP program qualitatively and some also quantitatively
310 bool selftest();
311
312 bool need_ocep_correction(const std::string& model) const {
313 return (model=="ocep") or (model=="dcep") or (model=="mrks");
314 }
315
316 bool need_dcep_correction(const std::string& model) const {
317 return (model=="dcep");
318 }
319
320 bool need_mrks_correction(const std::string& model) const {
321 return (model=="mrks");
322 }
323
324 /// print orbital energies in reverse order with optional shift
325 void print_orbens(const tensorT orbens) const {
326 for (long i = orbens.size() - 1; i >= 0; i--) {
327 printf(" e%2.2lu = %12.8f Eh\n", i, orbens(i));
328 }
329 }
330
331 OEPResults compute_and_print_final_energies(const std::string model, const real_function_3d& Voep,
332 const vecfuncT& KS_nemo, const tensorT& KS_Fock,
333 const vecfuncT& HF_nemo, const tensorT& HF_Fock) const;
334
335 /// compute density from orbitals with ragularization (Bischoff, 2014_1, equation (19))
337 real_function_3d density = 2.0*R_square*dot(world, nemo, nemo); // 2 because closed shell
338 return density;
339 }
340
341 /// compute Delta rho as an indicator for the result's quality
342 double compute_delta_rho(const real_function_3d rho_HF, const real_function_3d rho_KS) const {
343 // from Ospadov_2017, equation (26)
344 real_function_3d rho_diff = abs(rho_KS - rho_HF);
345 double Drho = rho_diff.trace();
346 return Drho;
347 }
348
349 /// compute Slater potential (Kohut, 2014, equation (15))
351
352 Exchange<double,3> K(world,reference->get_calc()->param.lo());
353 K.set_bra_and_ket(R_square * nemo, nemo);
354 const vecfuncT Knemo = K(nemo);
355 // 2.0*R_square in numerator and density (rho) cancel out upon division
356 real_function_3d numerator = -1.0*dot(world, nemo, Knemo);
357 real_function_3d rho = dot(world, nemo, nemo);
358
359 // long-range asymptotic behavior for Slater potential is \int 1/|r-r'| * |phi_HOMO|^2 dr'
360 // in order to compute this lra, use Coulomb potential with only HOMO density (= |phi_HOMO|^2)
361// Coulomb J(world);
362// J.reset_poisson_operator_ptr(param.lo(),param.econv());
363// real_function_3d lra = -1.0*J.compute_potential(R_square*square(nemo[homo_ind]));
364 Coulomb<double,3> J(world,this);
366// print("compute long-range part of the Slater potential from the full molecular density");
367 if (oep_param.saving_amount() >= 3) save(lra, "lra_slater");
368
370 real_function_3d one=real_factory_3d(world).functor([](const coord_3d& r){return 1.0;});
371 std::vector<real_function_3d> args={R_square*rho,numerator,rho,zero,one,lra};
373
377 return VSlater;
378 }
379
380
381 /// compute the total kinetic energy density of equation (6) from Kohut
382
383 /// return without the NCF and factor 2 for closed shell !
385
386 // compute tau = 1/2 * sum |\nabla phi_i|^2
387 // = 1/2 * sum {(\nabla R)^2 * nemo_i^2 + 2 * R * nemo_i * (\nabla R) * (\nabla nemo_i)) + R^2 * (\nabla nemo_i)^2}
388 // = 1/2 * R^2 * sum {U1dot * nemo_i^2 + 2 * nemo_i * U1 * (\nabla nemo_i)) + (\nabla nemo_i)^2}
389
390 // get \nabla R and (\nabla R)^2 via and U1 = -1/R \nabla R and U1dot = (1/R \nabla R)^2
391 const vecfuncT U1 = this->ncf->U1vec();
393 const real_function_3d U1dot = real_factory_3d(world).functor(u1_dot_u1).truncate_on_project();
394
395 real_function_3d u1u1term=U1dot*dot(world,nemo,nemo);
398
399 for (int idim=0; idim<3; ++idim) {
401 if(get_calc_param().dft_deriv() == "bspline") D.set_bspline1();
402 vecfuncT nemo_copy=copy(world,nemo);
403 refine(world,nemo_copy);
404 std::vector<real_function_3d> dnemo=apply(world,D,nemo_copy);
405 u1dnterm+=U1[idim]*dot(world,nemo_copy,dnemo);
406 refine(world,dnemo);
407 dndnterm+=dot(world,dnemo,dnemo);
408 }
409
410 real_function_3d tau=0.5*(u1u1term - 2.0*u1dnterm + dndnterm);
411
412 return tau;
413
414 }
415
416 /// compute the Pauli kinetic energy density divided by the density tau_P/rho with equation (16) from Ospadov, 2017
418
419 // compute the numerator tau_P
420
421 // get \nabla nemo
422 std::vector<vecfuncT> grad_nemo(nemo.size());
423 for (size_t i = 0; i < nemo.size(); i++) {
424 vecfuncT nemo_copy=copy(world,nemo);
425 refine(world,nemo_copy);
426
427 if(get_calc_param().dft_deriv() == "bspline") grad_nemo[i] = grad_bspline_one(nemo_copy[i]); // gradient using b-spline
428 else grad_nemo[i] = grad(nemo_copy[i]); // default gradient using abgv
429 }
430
431 vecfuncT grad_nemo_term;
432 for (size_t i = 0; i < nemo.size(); i++) {
433 for (size_t j = i + 1; j < nemo.size(); j++) {
434 vecfuncT tmp = nemo[i]*grad_nemo[j] - nemo[j]*grad_nemo[i];
435 grad_nemo_term.push_back(dot(world, tmp, tmp));
436 }
437 }
438 real_function_3d numerator = sum(world, grad_nemo_term); // numerator = tau_P * 2 * rho / R^4
439
440 return numerator;
441
442 }
443
444 /// compute correction of the given model
445
446 /// shift of the diagonal elements of the fock matrix results in a global shift
447 /// of the potential
448 /// \f[
449 /// \frac{\bar \epsilon}{\rho} = \frac{1}{\rho}\sum_{ij}\phi_i(F_ij+\delta_ij s)\phi_j
450 /// = \frac{1}{\rho} ( \sum_{ij}\phi_i F_ij \phi_j + s\sum_i\phi_i\phi_i )
451 /// = s + \frac{1}{\rho} \sum_{ij}\phi_i F_ij \phi_j
452 /// \f]
454 const vecfuncT& nemoHF, const vecfuncT& nemoKS,
455 const tensorT& fockHF, const tensorT& fockKS) const {
456
457 if (fockKS.normf()<1.e-10) {
459 return zero;
460 }
461
462 // compute HOMO energies and the long-range asymptotics
463 auto [eval, evec] = syev(fockKS);
464 double homoKS = -eval.max();
465
466 auto [eval1, evec1] = syev(fockHF);
467 double homoHF = -eval1.max();
468
469 double longrange=homoHF-homoKS;
470
471 tensorT fock1=copy(fockKS);
472 for (int i=0; i<fock1.dim(0); ++i) fock1(i,i)-=longrange;
473
474 // 2.0*R_square in numerator and density (rho) cancel out upon division
475// real_function_3d numeratorHF=-1.0*compute_energy_weighted_density_local(nemoHF,fockHF);
476// real_function_3d numeratorHF=-1.0*compute_energy_weighted_density(nemoHF,eigvalsHF);
477 real_function_3d numeratorKS=-1.0*compute_energy_weighted_density_local(nemoKS,fock1);
478// real_function_3d numeratorKS=-1.0*compute_energy_weighted_density(nemoKS,eval);
479
480 // 2.0*R_square in numerator and density (rho) cancel out upon division
481 real_function_3d densityKS = dot(world, nemoKS, nemoKS);
482 real_function_3d densityHF = dot(world, nemoHF, nemoHF);
483
485 std::vector<real_function_3d> args={densityKS,ocep_numerator_HF,densityHF,
486 numeratorKS,densityKS,lra_func};
488
491 real_function_3d correction=multi_to_multi_op_values(op,args)[0];
492
493
494 return correction;
495
496 }
497
498 /// return without the NCF and factor 2 for closed shell !
499
500 /// follow Eq. (4) of Ryabinkin2014
502 const tensorT& fock) const {
503 return dot(world,nemo,transform(world,nemo,fock));
504 }
505
506 /// compute correction of the given model
508 const vecfuncT& nemoHF, const vecfuncT& nemoKS) const {
509
510 // 2.0*R_square in numerator and density (rho) cancel out upon division
511// real_function_3d numeratorHF=compute_total_kinetic_density(nemoHF);
513
514 // 2.0*R_square in numerator and density (rho) cancel out upon division
515 real_function_3d densityKS = dot(world, nemoKS, nemoKS);
516 real_function_3d densityHF = dot(world, nemoHF, nemoHF);
517
518 real_function_3d lra_func=real_factory_3d(world).functor([](const coord_3d& r)
519 {return 0.0;});
520
521 std::vector<real_function_3d> args={densityKS,dcep_numerator_HF,densityHF,
522 numeratorKS,densityKS,lra_func};
524
527 real_function_3d correction=multi_to_multi_op_values(op,args)[0];
528
529 return correction;
530 }
531
532 /// compute correction of the given model
534 const vecfuncT& nemoHF, const vecfuncT& nemoKS) const {
535
536 // 2.0*R_square in numerator and density (rho) cancel out upon division
537// real_function_3d numeratorHF=compute_Pauli_kinetic_density(nemoHF);
539
540 // 2.0*R_square in numerator and density (rho) cancel out upon division
541 real_function_3d densityKS = dot(world, nemoKS, nemoKS);
542 real_function_3d densityHF = dot(world, nemoHF, nemoHF);
543
544 // longrange correction is zero
545 real_function_3d lra_func=real_factory_3d(world).functor([](const coord_3d& r) {return 0.0;});
546
547 real_function_3d denssq=square(densityKS);
548 std::vector<real_function_3d> args={densityKS,mrks_numerator_HF,densityHF,
549 numeratorKS,densityKS,lra_func};
551
554 op.square_denominator=true;
555 real_function_3d correction=0.5*multi_to_multi_op_values(op,args)[0];
556
557 return correction;
558 }
559
560 /// compute all potentials from given nemos except kinetic energy
561 void compute_nemo_potentials(const vecfuncT& nemo, vecfuncT& Jnemo, vecfuncT& Unemo) const {
562
563 // compute Coulomb part
564 compute_coulomb_potential(nemo, Jnemo);
565
566 // compute nuclear potential part
567 Nuclear<double,3> Unuc(world, this->ncf);
568 Unemo = Unuc(nemo);
569
570 }
571
572 /// compute Coulomb potential
573 void compute_coulomb_potential(const vecfuncT& nemo, vecfuncT& Jnemo) const {
574
575 Coulomb<double,3> J(world, this);
578 Jnemo = J(nemo);
579 truncate(world, Jnemo);
580
581 }
582
583 /// compute exchange potential (needed for Econv)
584 void compute_exchange_potential(const vecfuncT& nemo, vecfuncT& Knemo) const {
585
586 Exchange<double,3> K(world,this->get_calc()->param.lo());
587 K.set_bra_and_ket(R_square * nemo, nemo);
588 Knemo = K(nemo);
589 truncate(world, Knemo);
590
591 }
592
593 /// compute Evir using Levy-Perdew virial relation (Kohut_2014, (43) or Ospadov_2017, (25))
594 double compute_exchange_energy_vir(const vecfuncT& nemo, const real_function_3d Vx) const {
595
596 // make vector of functions r = (x, y, z)
597 auto monomial_x = [] (const coord_3d& r) {return r[0];};
598 auto monomial_y = [] (const coord_3d& r) {return r[1];};
599 auto monomial_z = [] (const coord_3d& r) {return r[2];};
600 vecfuncT r(3);
601 r[0]=real_factory_3d(world).functor(monomial_x);
602 r[1]=real_factory_3d(world).functor(monomial_y);
603 r[2]=real_factory_3d(world).functor(monomial_z);
604
605 real_function_3d rhonemo = 2.0*dot(world, nemo, nemo); // 2 because closed shell
606
607 real_function_3d rhoterm = 3*rhonemo + dot(world, r, -2.0*ncf->U1vec()*rhonemo + grad(rhonemo,true));
608 double Ex = inner(Vx, R_square*rhoterm);
609 return Ex;
610
611 }
612
613 /// compute exchange energy using the expectation value of the exchange operator
614 double compute_exchange_energy_conv(const vecfuncT phi, const vecfuncT Kphi) const {
615
616 double Ex = -1.0*inner(world, phi, Kphi).sum();
617 return Ex;
618
619 }
620
621 /// compute all energy contributions except exchange and sum up for total energy
622 /// the exchange energy must be computed priorly with the compute_exchange_energy_... methods
623 std::vector<double> compute_energy(const vecfuncT& nemo, const double E_X) const {
624
625 // compute kinetic energy
626 double E_kin = compute_kinetic_energy(nemo);
627
629
630 // compute external potential (nuclear attraction)
631 real_function_3d Vext = calc->potentialmanager->vnuclear();
632 Coulomb<double,3> J(world,this);
634
635 // compute remaining energies: nuclear attraction, Coulomb, nuclear repulsion
636 // computed as expectation values (see Szabo, Ostlund (3.81))
637 const double E_ext = inner(Vext,density); // 2 because closed shell
638 const double E_J = 0.5*inner(density,Jpotential);
639 const double E_nuc = calc->molecule.nuclear_repulsion_energy();
640 double energy = E_kin + E_ext + E_J + E_X + E_nuc;
641
642 if (world.rank() == 0) {
643 printf("\n kinetic energy %15.8f Eh\n", E_kin);
644 printf(" electron-nuclear attraction energy %15.8f Eh\n", E_ext);
645 printf(" Coulomb energy %15.8f Eh\n", E_J);
646 printf(" exchange energy %15.8f Eh\n", E_X);
647 printf(" nuclear-nuclear repulsion energy %15.8f Eh\n", E_nuc);
648 printf(" total energy %15.8f Eh\n\n", energy);
649 }
650 return {energy,E_kin,E_ext,E_J,E_X};
651
652 }
653
654 /// compute diagonal elements of Fock matrix
656 const vecfuncT& phi, const vecfuncT& Kphi, const real_function_3d& Vx) const {
657 return KS_eigvals - inner(world, phi, Kphi) - inner(world, phi, Vx*phi);
658 }
659
660 /// cumpute E^(0) = \sum_i \epsilon_i^KS
661 double compute_E_zeroth(const tensorT eigvals) const {
662 double E_0 = 0.0;
663 for (long i = 0; i < eigvals.size(); i++) {
664 E_0 += eigvals(i);
665 }
666 E_0 *= 2.0; // closed shell: every orbital energy must be counted twice
667 return E_0;
668 }
669
670 /// compute E^(1) = 1/2*\sum_ij <ij||ij> - \sum_i <i|J + Vx|i> = \sum_i <i|- 0.5*J - 0.5*K - Vx|i>
671 double compute_E_first(const vecfuncT phi, const vecfuncT Jphi, const vecfuncT Kphi, const real_function_3d Vx) const {
672
673 //compute expectation values:
674 const double E_J = inner(world, phi, Jphi).sum();
675 const double E_K = inner(world, phi, Kphi).sum();
676 const double E_Vx = inner(world, phi, Vx*phi).sum();
677 printf(" E_J = %15.8f Eh\n", E_J);
678 printf(" E_K = %15.8f Eh\n", E_K);
679 printf(" E_Vx = %15.8f Eh\n", E_Vx);
680 const double E_nuc = calc->molecule.nuclear_repulsion_energy();
681
682 double E_1 = -1.0*(E_J + E_K + 2.0*E_Vx) + E_nuc;
683 return E_1;
684
685 }
686
687};
688
689
690
691} /* namespace madness */
692
693#endif /* SRC_APPS_CHEM_OEP_H_ */
double w(double t, double eps)
Definition DKops.h:22
Operators for the molecular HF and DFT code.
long dim(int i) const
Returns the size of dimension i.
Definition basetensor.h:147
long size() const
Returns the number of elements in the tensor.
Definition basetensor.h:138
Definition SCFOperators.h:334
Function< T, NDIM > compute_potential(const Function< T, NDIM > &density) const
given a density compute the Coulomb potential
Definition SCFOperators.h:432
const real_function_3d & potential() const
getter for the Coulomb potential
Definition SCFOperators.h:421
Implements derivatives operators with variety of boundary conditions on simulation domain.
Definition derivative.h:266
Definition SCFOperators.h:104
Exchange & set_bra_and_ket(const vecfuncT &bra, const vecfuncT &ket)
Definition SCFOperators.cc:712
T trace() const
Returns global value of int(f(x),x) ... global comm required.
Definition mra.h:1154
bool compressed
Definition mra.h:1168
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:69
static void print_parameters()
Definition molecule.cc:115
real_function_3d R_square
the square of the nuclear correlation factor
Definition nemo.h:319
double compute_kinetic_energy(const std::vector< Function< T, NDIM > > &nemo) const
compute kinetic energy as square of the "analytical" expectation value
Definition nemo.h:183
World & world
Definition nemo.h:310
The Nemo class.
Definition nemo.h:326
void set_protocol(const double thresh)
adapt the thresholds consistently to a common value
Definition nemo.h:637
const NemoCalculationParameters & get_nemo_param() const
Definition nemo.h:503
std::shared_ptr< SCF > get_calc() const
Definition nemo.h:501
const CalculationParameters & get_calc_param() const
Definition nemo.h:504
std::shared_ptr< SCF > calc
Definition nemo.h:588
void load_mos(World &w)
Definition nemo.h:414
Molecule & molecule()
return a reference to the molecule
Definition nemo.h:512
functor for a local U1 dot U1 potential
Definition correlationfactor.h:532
Definition SCFOperators.h:455
Definition Results.h:327
Definition oep.h:80
OEP_Parameters(World &world, const commandlineparser &parser)
Definition oep.h:107
static constexpr char const * tag
Definition oep.h:82
std::vector< std::string > model() const
Definition oep.h:134
unsigned int maxiter() const
Definition oep.h:138
double dens_thresh_inv() const
Definition oep.h:143
bool restart() const
Definition oep.h:136
OEP_Parameters(const OEP_Parameters &other)=default
bool no_compute() const
Definition oep.h:137
unsigned int save_iter_corrections() const
Definition oep.h:145
void set_derived_values(const CalculationParameters &cparam)
Definition oep.h:119
unsigned int saving_amount() const
Definition oep.h:144
double dens_thresh_hi() const
Definition oep.h:141
OEP_Parameters()
Definition oep.h:84
std::vector< double > kain_param() const
Definition oep.h:147
double levelshift() const
Definition oep.h:139
std::string get_tag() const override
Definition oep.h:114
double dens_thresh_lo() const
Definition oep.h:142
Definition oep.h:152
bool selftest()
The following function tests all essential parts of the OEP program qualitatively and some also quant...
Definition madness/chem/oep.cc:405
bool need_mrks_correction(const std::string &model) const
Definition oep.h:320
void set_reference(const std::shared_ptr< Nemo > reference1)
Definition oep.h:230
OEP_Parameters oep_param
parameters for this OEP calculation
Definition oep.h:157
static void help()
Definition oep.h:212
double compute_exchange_energy_vir(const vecfuncT &nemo, const real_function_3d Vx) const
compute Evir using Levy-Perdew virial relation (Kohut_2014, (43) or Ospadov_2017, (25))
Definition oep.h:594
real_function_3d compute_total_kinetic_density(const vecfuncT &nemo) const
compute the total kinetic energy density of equation (6) from Kohut
Definition oep.h:384
void save_restartdata(const Tensor< double > &fock) const
Definition madness/chem/oep.cc:74
virtual std::shared_ptr< Fock< double, 3 > > make_fock_operator() const
the OEP Fock operator is the HF Fock operator without exchange but with the OEP
Definition madness/chem/oep.cc:122
Tensor< double > compute_fock_diagonal_elements(const Tensor< double > &KS_eigvals, const vecfuncT &phi, const vecfuncT &Kphi, const real_function_3d &Vx) const
compute diagonal elements of Fock matrix
Definition oep.h:655
double compute_exchange_energy_conv(const vecfuncT phi, const vecfuncT Kphi) const
compute exchange energy using the expectation value of the exchange operator
Definition oep.h:614
double compute_delta_rho(const real_function_3d rho_HF, const real_function_3d rho_KS) const
compute Delta rho as an indicator for the result's quality
Definition oep.h:342
void print_parameters(std::vector< std::string > what) const
Definition oep.h:238
void compute_nemo_potentials(const vecfuncT &nemo, vecfuncT &Jnemo, vecfuncT &Unemo) const
compute all potentials from given nemos except kinetic energy
Definition oep.h:561
real_function_3d compute_slater_potential(const vecfuncT &nemo) const
compute Slater potential (Kohut, 2014, equation (15))
Definition oep.h:350
virtual double value()
Definition oep.h:251
bool need_dcep_correction(const std::string &model) const
Definition oep.h:316
OEPResults iterate(const std::string model, const vecfuncT &HF_nemo, const tensorT &HF_eigvals, vecfuncT &KS_nemo, tensorT &KS_Fock, real_function_3d &Voep, const real_function_3d Vs) const
Definition madness/chem/oep.cc:217
real_function_3d compute_energy_weighted_density_local(const vecfuncT &nemo, const tensorT &fock) const
return without the NCF and factor 2 for closed shell !
Definition oep.h:501
real_function_3d compute_mrks_correction(const real_function_3d &mrks_numerator_HF, const vecfuncT &nemoHF, const vecfuncT &nemoKS) const
compute correction of the given model
Definition oep.h:533
std::tuple< Tensor< double >, vecfuncT > recompute_HF(const vecfuncT &HF_nemo) const
Definition madness/chem/oep.cc:110
std::string name() const
Definition oep.h:210
virtual double value(const Tensor< double > &x)
Should return the value of the objective function.
Definition oep.h:259
double compute_E_first(const vecfuncT phi, const vecfuncT Jphi, const vecfuncT Kphi, const real_function_3d Vx) const
compute E^(1) = 1/2*\sum_ij <ij||ij> - \sum_i <i|J + Vx|i> = \sum_i <i|- 0.5*J - 0....
Definition oep.h:671
real_function_3d compute_Pauli_kinetic_density(const vecfuncT &nemo) const
compute the Pauli kinetic energy density divided by the density tau_P/rho with equation (16) from Osp...
Definition oep.h:417
OEP(World &world, const OEP_Parameters &oepparam, const std::shared_ptr< const Nemo > &reference)
Definition oep.h:171
void compute_coulomb_potential(const vecfuncT &nemo, vecfuncT &Jnemo) const
compute Coulomb potential
Definition oep.h:573
std::shared_ptr< const Nemo > get_reference() const
Definition oep.h:234
void print_orbens(const tensorT orbens) const
print orbital energies in reverse order with optional shift
Definition oep.h:325
nlohmann::json analyze() const override
results are computed in compute_and_print_final_energies
Definition oep.h:282
void load_restartdata(Tensor< double > &fock)
Definition madness/chem/oep.cc:92
double compute_E_zeroth(const tensorT eigvals) const
cumpute E^(0) = \sum_i \epsilon_i^KS
Definition oep.h:661
real_function_3d compute_density(const vecfuncT &nemo) const
compute density from orbitals with ragularization (Bischoff, 2014_1, equation (19))
Definition oep.h:336
static void print_parameters()
Definition oep.h:222
real_function_3d get_final_potential() const
Definition oep.h:247
real_function_3d Vfinal
the final local potential
Definition oep.h:164
std::vector< OEPResults > results
collection of results
Definition oep.h:167
std::shared_ptr< const Nemo > reference
the wave function reference that determines the local potential
Definition oep.h:161
OEP(World &world, const commandlineparser &parser)
Definition oep.h:191
void compute_exchange_potential(const vecfuncT &nemo, vecfuncT &Knemo) const
compute exchange potential (needed for Econv)
Definition oep.h:584
void output_calc_info_schema(const double &energy) const
update the json file with calculation input and output
Definition madness/chem/oep.cc:64
std::vector< double > compute_energy(const vecfuncT &nemo, const double E_X) const
Definition oep.h:623
bool need_ocep_correction(const std::string &model) const
Definition oep.h:312
OEPResults compute_and_print_final_energies(const std::string model, const real_function_3d &Voep, const vecfuncT &KS_nemo, const tensorT &KS_Fock, const vecfuncT &HF_nemo, const tensorT &HF_Fock) const
Definition madness/chem/oep.cc:130
real_function_3d compute_dcep_correction(const real_function_3d &dcep_numerator_HF, const vecfuncT &nemoHF, const vecfuncT &nemoKS) const
compute correction of the given model
Definition oep.h:507
real_function_3d compute_ocep_correction(const real_function_3d &ocep_numerator_HF, const vecfuncT &nemoHF, const vecfuncT &nemoKS, const tensorT &fockHF, const tensorT &fockKS) const
compute correction of the given model
Definition oep.h:453
double solve(const vecfuncT &HF_nemo)
Definition madness/chem/oep.cc:22
class for holding the parameters for calculation
Definition QCCalculationParametersBase.h:294
virtual void read_input_and_commandline_options(World &world, const commandlineparser &parser, const std::string tag)
Definition QCCalculationParametersBase.h:330
T get(const std::string key) const
Definition QCCalculationParametersBase.h:304
void print(const std::string header="", const std::string footer="") const
print all parameters
Definition QCCalculationParametersBase.cc:22
void set_derived_value(const std::string &key, const T &value)
Definition QCCalculationParametersBase.h:408
virtual real_function_3d density() const
Definition QCPropertyInterface.h:25
A tensor is a multidimensional array.
Definition tensor.h:317
float_scalar_type normf() const
Returns the Frobenius norm of the tensor.
Definition tensor.h:1726
Tensor< T > & fill(T x)
Inplace fill with a scalar (legacy name)
Definition tensor.h:562
A parallel world class.
Definition world.h:132
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:320
double(* energy)()
Definition derivatives.cc:58
static double lo
Definition dirac-hatom.cc:23
real_function_3d mask
Definition dirac-hatom.cc:27
vecfuncT K(vecfuncT &ket, vecfuncT &bra, vecfuncT &vf)
Tensor< double > op(const Tensor< double > &x)
Definition kain.cc:508
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
void print_header2(const std::string &s)
medium section heading
Definition print.cc:54
double abs(double x)
Definition complexfun.h:48
Function< T, NDIM > square(const Function< T, NDIM > &f, bool fence=true)
Create a new function that is the square of f - global comm only if not reconstructed.
Definition mra.h:2746
std::vector< Function< T, NDIM > > grad_bspline_one(const Function< T, NDIM > &f, bool refine=false, bool fence=true)
Definition vmra.h:2093
void truncate(World &world, response_space &v, double tol, bool fence)
Definition basic_operators.cc:31
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const Tensor< R > &c, bool fence=true)
Transforms a vector of functions according to new[i] = sum[j] old[j]*c[j,i].
Definition vmra.h:707
std::vector< Function< T, NDIM > > multi_to_multi_op_values(const opT &op, const std::vector< Function< T, NDIM > > &vin, const bool fence=true)
apply op on the input vector yielding an output vector of functions
Definition vmra.h:1882
FunctionFactory< double, 3 > real_factory_3d
Definition functypedefs.h:108
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:225
response_space apply(World &world, std::vector< std::vector< std::shared_ptr< real_convolution_3d > > > &op, response_space &f)
Definition basic_operators.cc:43
void refine(World &world, const std::vector< Function< T, NDIM > > &vf, bool fence=true)
refine the functions according to the autorefine criteria
Definition vmra.h:196
Function< TENSOR_RESULT_TYPE(T, R), NDIM > dot(World &world, const std::vector< Function< T, NDIM > > &a, const std::vector< Function< R, NDIM > > &b, bool fence=true)
Multiplies and sums two vectors of functions r = \sum_i a[i] * b[i].
Definition vmra.h:1565
double inner(response_space &a, response_space &b)
Definition response_functions.h:640
vector< functionT > vecfuncT
Definition corepotential.cc:58
void refine_to_common_level(World &world, std::vector< Function< T, NDIM > > &vf, bool fence=true)
refine all functions to a common (finest) level
Definition vmra.h:206
std::vector< Function< T, NDIM > > grad(const Function< T, NDIM > &f, bool refine=false, bool fence=true)
shorthand gradient operator
Definition vmra.h:2033
void save(const Function< T, NDIM > &f, const std::string name)
Definition mra.h:2835
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition mra.h:2066
void syev(const Tensor< T > &A, Tensor< T > &V, Tensor< typename Tensor< T >::scalar_type > &e)
Real-symmetric or complex-Hermitian eigenproblem.
Definition lapack.cc:969
Definition test_ar.cc:204
Definition CalculationParameters.h:51
double econv() const
Definition CalculationParameters.h:149
int nalpha() const
Definition CalculationParameters.h:170
int nbeta() const
Definition CalculationParameters.h:171
very simple command line parser
Definition commandlineparser.h:15
Class to compute terms of the potential.
Definition oep.h:22
double log_high
Definition oep.h:27
std::vector< Tensor< double > > operator()(const Key< 3 > &key, const std::vector< Tensor< double > > &t) const
Definition oep.h:40
double log_low
Definition oep.h:27
bool square_denominator
Definition oep.h:28
std::size_t get_result_size() const
Definition oep.h:34
double eps_regularize
Definition oep.h:26
divide_add_interpolate(double hi, double lo, double eps_regularize)
Definition oep.h:30
double thresh_high
Definition oep.h:24
double thresh_low
Definition oep.h:25
Definition dirac-hatom.cc:112
InputParameters param
Definition tdse.cc:203
#define ITERATOR(t, exp)
Definition tensor_macros.h:249
#define IND
Definition tensor_macros.h:204
AtomicInt sum
Definition test_atomicint.cc:46
constexpr coord_t one(1.0)