48 double exactexchange = 0.0;
51 std::vector<std::string> functional_names =
54 if (functional_names.size() > 2) {
55 throw std::runtime_error(
"Too many functional names");
56 }
else if (functional_names.empty()) {
57 throw std::runtime_error(
"Specify at least one functional");
60 for (
const std::string& functional_name : functional_names) {
61 int func_id = map.getID(functional_name);
68 if (xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0) {
69 throw std::runtime_error(
70 (boost::format(
"Functional %s not found\n") % functional_name).str());
73 if (exactexchange > 0 && func.cam_alpha > 0) {
75 throw std::runtime_error(
76 "You have specified two functionals with exact exchange");
79 exactexchange += func.cam_alpha;
186 double rho_a,
double rho_b,
double sigma_aa,
double sigma_ab,
187 double sigma_bb)
const {
192 xc_func_type xfunc_pol;
193 if (xc_func_init(&xfunc_pol,
xfunc_id, XC_POLARIZED) != 0) {
194 throw std::runtime_error(
195 "Failed to initialize polarized exchange XC "
196 "functional in EvaluateXCSpin.");
199 xc_func_type cfunc_pol;
200 bool cfunc_pol_init =
false;
202 if (xc_func_init(&cfunc_pol,
cfunc_id, XC_POLARIZED) != 0) {
203 xc_func_end(&xfunc_pol);
204 throw std::runtime_error(
205 "Failed to initialize polarized correlation XC "
206 "functional in EvaluateXCSpin.");
208 cfunc_pol_init =
true;
211 double rho[2] = {rho_a, rho_b};
213 switch (xfunc_pol.info->family) {
214 case XC_FAMILY_LDA: {
215 double vrho[2] = {0.0, 0.0};
216 xc_lda_exc_vxc(&xfunc_pol, 1, rho, &result.
f_xc, vrho);
222 case XC_FAMILY_HYB_GGA: {
223 double sigma[3] = {sigma_aa, sigma_ab, sigma_bb};
224 double vrho[2] = {0.0, 0.0};
225 double vsigma[3] = {0.0, 0.0, 0.0};
226 xc_gga_exc_vxc(&xfunc_pol, 1, rho, sigma, &result.
f_xc, vrho, vsigma);
235 xc_func_end(&xfunc_pol);
236 if (cfunc_pol_init) {
237 xc_func_end(&cfunc_pol);
239 throw std::runtime_error(
"Unsupported XC family for polarized DFT.");
245 switch (cfunc_pol.info->family) {
246 case XC_FAMILY_LDA: {
247 double vrho[2] = {0.0, 0.0};
248 xc_lda_exc_vxc(&cfunc_pol, 1, rho, &temp.
f_xc, vrho);
254 case XC_FAMILY_HYB_GGA: {
255 double sigma[3] = {sigma_aa, sigma_ab, sigma_bb};
256 double vrho[2] = {0.0, 0.0};
257 double vsigma[3] = {0.0, 0.0, 0.0};
258 xc_gga_exc_vxc(&cfunc_pol, 1, rho, sigma, &temp.
f_xc, vrho, vsigma);
267 xc_func_end(&xfunc_pol);
268 xc_func_end(&cfunc_pol);
269 throw std::runtime_error(
270 "Unsupported correlation family for polarized DFT.");
281 xc_func_end(&xfunc_pol);
282 if (cfunc_pol_init) {
283 xc_func_end(&cfunc_pol);
291 const Eigen::MatrixXd& density_matrix)
const {
292 assert(density_matrix.isApprox(density_matrix.transpose()) &&
293 "Density matrix has to be symmetric!");
297#pragma omp parallel for schedule(guided) reduction(+ : vxc)
298 for (
Index i = 0; i <
grid_.getBoxesSize(); ++i) {
304 double EXC_box = 0.0;
310 1.e-40 / double(density_matrix.rows()) / double(density_matrix.rows());
311 if (DMAT_here.cwiseAbs2().maxCoeff() < cutoff) {
315 Eigen::MatrixXd Vxc_here =
316 Eigen::MatrixXd::Zero(DMAT_here.rows(), DMAT_here.cols());
318 const std::vector<Eigen::Vector3d>& points = box.
getGridPoints();
324 Eigen::VectorXd temp = ao.
values.transpose() * DMAT_here;
325 double rho = 0.5 * temp.dot(ao.
values);
326 const double weight = weights[p];
328 if (rho * weight < 1.e-20) {
332 const Eigen::Vector3d rho_grad = temp.transpose() * ao.
derivatives;
337 EXC_box += weight * rho * xc.
f_xc;
342 Vxc_here.noalias() += temp * ao.
values.transpose();
354 const Eigen::MatrixXd& dmat_alpha,
const Eigen::MatrixXd& dmat_beta)
const {
355 assert(dmat_alpha.isApprox(dmat_alpha.transpose()) &&
356 "Alpha density matrix has to be symmetric!");
357 assert(dmat_beta.isApprox(dmat_beta.transpose()) &&
358 "Beta density matrix has to be symmetric!");
362 Eigen::MatrixXd::Zero(dmat_alpha.rows(), dmat_alpha.cols());
363 result.
vxc_beta = Eigen::MatrixXd::Zero(dmat_beta.rows(), dmat_beta.cols());
367 Eigen::MatrixXd vxc_alpha_private =
368 Eigen::MatrixXd::Zero(dmat_alpha.rows(), dmat_alpha.cols());
369 Eigen::MatrixXd vxc_beta_private =
370 Eigen::MatrixXd::Zero(dmat_beta.rows(), dmat_beta.cols());
371 double exc_private = 0.0;
373#pragma omp for schedule(guided)
374 for (
Index i = 0; i <
grid_.getBoxesSize(); ++i) {
384 1.e-40 / double(dmat_alpha.rows()) / double(dmat_alpha.rows());
385 if (std::max(DMa.cwiseAbs2().maxCoeff(), DMb.cwiseAbs2().maxCoeff()) <
390 Eigen::MatrixXd Vxc_a_here =
391 Eigen::MatrixXd::Zero(DMa.rows(), DMa.cols());
392 Eigen::MatrixXd Vxc_b_here =
393 Eigen::MatrixXd::Zero(DMb.rows(), DMb.cols());
395 const std::vector<Eigen::Vector3d>& points = box.
getGridPoints();
401 Eigen::VectorXd temp_a = DMa * ao.
values;
402 Eigen::VectorXd temp_b = DMb * ao.
values;
404 const double rho_a = ao.
values.dot(temp_a);
405 const double rho_b = ao.
values.dot(temp_b);
406 const double rho = rho_a + rho_b;
407 const double weight = weights[p];
409 if (rho * weight < 1.e-20) {
415 const Eigen::Vector3d grad_a =
417 const Eigen::Vector3d grad_b =
420 const double sigma_aa = grad_a.dot(grad_a);
421 const double sigma_ab = grad_a.dot(grad_b);
422 const double sigma_bb = grad_b.dot(grad_b);
427 exc_private += weight * rho * xc.
f_xc;
429 if (
xfunc.info->family == XC_FAMILY_LDA) {
431 Eigen::VectorXd wa = weight * (0.5 * xc.
vrho_a) * ao.
values;
432 Eigen::VectorXd wb = weight * (0.5 * xc.
vrho_b) * ao.
values;
434 Vxc_a_here.noalias() += wa * ao.
values.transpose();
435 Vxc_b_here.noalias() += wb * ao.
values.transpose();
449 Vxc_a_here.noalias() += wa * ao.
values.transpose();
450 Vxc_b_here.noalias() += wb * ao.
values.transpose();
460 result.
vxc_alpha += vxc_alpha_private + vxc_alpha_private.transpose();
461 result.
vxc_beta += vxc_beta_private + vxc_beta_private.transpose();
462 result.
energy += exc_private;