bool needs_VV10(int func_id, double & b, double & C) { b=0.0; C=0.0; bool ret=false; #ifdef XC_FLAGS_VV10 if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } // Get flag ret=func.info->flags & XC_FLAGS_VV10; if(ret) XC(nlc_coef)(&func, &b, &C); // Free functional xc_func_end(&func); } #endif return ret; }
bool laplacian_needed(int func_id) { // Is gradient necessary? bool lapl=0; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } switch(func.info->family) { case XC_FAMILY_MGGA: case XC_FAMILY_HYB_MGGA: lapl=1; break; } // Free functional xc_func_end(&func); } return lapl; }
bool is_range_separated(int func_id, bool check) { bool ans=false; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } // Get flag ans=func.info->flags & XC_FLAGS_HYB_CAM; // Free functional xc_func_end(&func); } if(check) { // Sanity check double w, a, b; range_separation(func_id,w,a,b); if(ans && w==0.0) fprintf(stderr,"Error in libxc detected - functional is marked range separated but with vanishing omega!\n"); else if(!ans && w!=0.0) fprintf(stderr,"Error in libxc detected - functional is not marked range separated but has nonzero omega!\n"); } return ans; }
bool is_kinetic(int func_id) { bool ans=0; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } switch(func.info->kind) { /* By default we assign exchange-correlation functionals as the exchange functional, since we check whether the exchange part includes exact exchange. */ case XC_KINETIC: ans=1; break; default: ans=0; } // Free functional xc_func_end(&func); } else // Dummy correlation ans=0; return ans; }
double exact_exchange(int func_id) { // Default - no exact exchange. double f=0.0; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } switch(func.info->family) { case XC_FAMILY_HYB_GGA: case XC_FAMILY_HYB_MGGA: // libxc prior to 2.0.0 // f=xc_hyb_gga_exx_coef(func.gga); // libxc 2.0.0 f=xc_hyb_exx_coef(&func); break; } xc_func_end(&func); } // printf("Fraction of exact exchange is %f.\n",f); return f; }
void test_neg_rho() { xc_func_type func; double rho[5][2] = { {9.03897273e-06,-1.00463992e-06}, {8.48383564e-06,-3.51231267e-07}, {1.45740621e-08,-2.94546705e-09}, {2.62778445e-07, -1.00191745e-07}, {2.55745103e-06, -1.54789964e-06} }; double sigma[5][3] = { {1.20122271e-08,4.83240746e-09,6.24774836e-09}, {1.54146602e-07,1.41584609e-07,1.36663204e-07}, {2.75312438e-08,2.75224049e-08,2.75135719e-08}, {1.90251649e-07,1.91241798e-07,1.92240989e-07}, {9.29562712e-09,7.83940082e-09, 8.05714636e-09} }; double vsigma[5][3]; double zk[5], vk[5][2]; int i, func_id; for(func_id=1; func_id<1000; func_id++){ if(xc_func_init(&func, func_id, XC_POLARIZED) != 0) continue; if(func_id == XC_LDA_C_2D_PRM || func_id == XC_GGA_X_LB) goto end; printf("\n%s:\n", func.info->name); switch(func.info->family){ case XC_FAMILY_LDA: xc_lda_exc_vxc(&func, 5, &rho[0][0], zk, &vk[0][0]); break; case XC_FAMILY_GGA: xc_gga_exc_vxc(&func, 5, &rho[0][0], &sigma[0][0], zk, &vk[0][0], &vsigma[0][0]); break; } switch(func.info->family){ case XC_FAMILY_LDA: for(i=0; i<5; i+=1) printf("%.8e %.8e %.8e %.8e %.8e\n", rho[i][0], rho[i][1], zk[i], vk[i][0], vk[i][1]); break; case XC_FAMILY_GGA: for(i=0; i<5; i+=1) printf("%.8e %.8e %.8e %.8e %.8e %.8e %.8e %.8e %.8e %.8e %.8e\n", rho[i][0], rho[i][1], sigma[i][0], sigma[i][1], sigma[i][2], zk[i], vk[i][0], vk[i][1], vsigma[i][0], vsigma[i][1], vsigma[i][2]); break; } end: xc_func_end(&func); } }
int VXCnr_eval_x(int x_id, int spin, int relativity, int np, double *rho_u, double *rho_d, double *ex, double *vxc, double *fxc, double *kxc) { xc_func_type func_x = {}; if (xc_func_init(&func_x, x_id, spin) != 0) { fprintf(stderr, "X functional %d not found\n", x_id); exit(1); } #if defined XC_SET_RELATIVITY xc_lda_x_set_params(&func_x, relativity); #endif _eval_xc(&func_x, spin, np, rho_u, rho_d, ex, vxc, fxc, kxc); xc_func_end(&func_x); return 1; }
void is_gga_mgga(int func_id, bool & gga, bool & mgga) { // Initialize gga=false; mgga=false; // Correlation and exchange functionals xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0) { ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } switch(func.info->family) { case XC_FAMILY_LDA: gga=false; mgga=false; break; case XC_FAMILY_GGA: case XC_FAMILY_HYB_GGA: gga=true; mgga=false; break; case XC_FAMILY_MGGA: case XC_FAMILY_HYB_MGGA: gga=false; mgga=true; break; default: { ERROR_INFO(); std::ostringstream oss; oss << "Functional family " << func.info->family << " not currently supported in ERKALE!\n"; throw std::runtime_error(oss.str()); } } // Free functional xc_func_end(&func); }
bool has_exc(int func_id) { bool ans=false; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } // Get flag ans=func.info->flags & XC_FLAGS_HAVE_EXC; // Free functional xc_func_end(&func); } return ans; }
void range_separation(int func_id, double & omega, double & alpha, double & beta, bool check) { // Defaults omega=0.0; alpha=0.0; beta=0.0; if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0){ ERROR_INFO(); std::ostringstream oss; oss << "Functional "<<func_id<<" not found!"; throw std::runtime_error(oss.str()); } switch(func.info->family) { case XC_FAMILY_HYB_GGA: case XC_FAMILY_HYB_MGGA: XC(hyb_cam_coef(&func,&omega,&alpha,&beta)); break; } xc_func_end(&func); } bool ans=is_range_separated(func_id,false); if(check) { if(ans && omega==0.0) { fprintf(stderr,"Error in libxc detected - functional is marked range separated but with vanishing omega!\n"); printf("Error in libxc detected - functional is marked range separated but with vanishing omega!\n"); } else if(!ans && omega!=0.0) { fprintf(stderr,"Error in libxc detected - functional is not marked range separated but has nonzero omega!\n"); printf("Error in libxc detected - functional is not marked range separated but has nonzero omega!\n"); } } // Work around libxc bug if(!ans) { omega=0.0; beta=0.0; } }
int VXCnr_eval_c(int c_id, int spin, int relativity, int np, double *rho_u, double *rho_d, double *ex, double *vxc, double *fxc, double *kxc) { int not0 = 1; xc_func_type func_c = {}; if (xc_func_init(&func_c, c_id, spin) != 0) { fprintf(stderr, "C functional %d not found\n", c_id); exit(1); } if (!(func_c.info->family == XC_FAMILY_HYB_GGA || func_c.info->family == XC_FAMILY_HYB_MGGA)) { not0 = 0; #if defined XC_SET_RELATIVITY xc_lda_x_set_params(&func_c, relativity); #endif _eval_xc(&func_c, spin, np, rho_u, rho_d, ex, vxc, fxc, kxc); } xc_func_end(&func_c); return not0; }
double VXChybrid_coeff(int xc_id, int spin) { xc_func_type func; double factor; if(xc_func_init(&func, xc_id, spin) != 0){ fprintf(stderr, "XC functional %d not found\n", xc_id); exit(1); } switch(func.info->family) { case XC_FAMILY_HYB_GGA: case XC_FAMILY_HYB_MGGA: factor = xc_hyb_exx_coef(&func); break; default: factor = 0; } xc_func_end(&func); return factor; }
void print_info(int func_id) { if(func_id>0) { xc_func_type func; if(xc_func_init(&func, func_id, XC_UNPOLARIZED) != 0) { ERROR_INFO(); std::ostringstream oss; oss << "\nFunctional "<<func_id<<" not found!\n"; throw std::runtime_error(oss.str()); } #if XC_MAJOR_VERSION < 3 printf("'%s', defined in the reference(s):\n%s\n", func.info->name, func.info->refs); #else printf("'%s', defined in the reference(s):\n", func.info->name); for(int i=0;i<5;i++) if(func.info->refs[i]!=NULL) printf("%s (DOI %s)\n",func.info->refs[i]->ref,func.info->refs[i]->doi); #endif xc_func_end(&func); } if(!has_exc(func_id)) { printf("The functional doesn't have an energy density, so the calculated energy is incorrect."); } }
void test_functional(int functional) { xc_func_type func; const xc_func_info_type *info; int i, j, k, p_max[6][5]; double max_diff[6][5], avg_diff[6][5], val[5]; #if defined(HAVE_FEENABLEEXCEPT) feenableexcept(FE_INVALID | FE_OVERFLOW); #endif /* initialize functional */ if(xc_func_init(&func, functional, nspin) != 0){ fprintf(stderr, "Functional '%d' not found\n", functional); exit(1); } info = func.info; if(functional == XC_LDA_C_2D_PRM) xc_lda_c_2d_prm_set_params(&func, 10.0); for(k=0; k<6; k++) for(j=0; j<5; j++){ avg_diff[k][j] = 0.0; p_max[k][j] = 0; max_diff[k][j] = -1.0; } for(i=0; xc_trial_points[i][0]!=0.0; i++){ double e, v_fd[5], f_fd[5][5], v_an[5], f_an[5][5]; for(j=0; j<5; j++) v_fd[j] = v_an[j] = 0.0; get_val(xc_trial_points[i], val); /* first, get the analytic gradients */ get_vxc(&func, val, &e, v_an); /* now get the numerical gradients */ first_derivative(&func, val, v_fd, 0); if(info->flags & XC_FLAGS_HAVE_FXC){ int i, j; /* initialize */ for(i=0; i<5; i++) for(j=0; j<5; j++) f_an[i][j] = f_fd[i][j] = 0.0; /* now get the second derivatives */ second_derivatives(&func, val, f_fd); get_fxc(&func, val, f_an); } /* make statistics */ for(j=0; j<5; j++){ double diff = fabs(v_an[j] - v_fd[j]); /* do not test in case of spin unpolarized or if spin down is zero */ if((nspin==1 || val[1]==0.0) && (j!=0 && j!=2)) continue; avg_diff[0][j] += diff; if(diff > max_diff[0][j]){ max_diff[0][j] = diff; p_max[0][j] = i; } if(info->flags & XC_FLAGS_HAVE_FXC){ for(k=0; k<5; k++){ /* do not test in case of spin unpolarized or if spin down is zero */ if((nspin==1 || val[1]==0.0) && (k!=0 && k!=2)) continue; diff = fabs(f_an[k][j] - f_fd[k][j]); avg_diff[k+1][j] += diff; if(diff > max_diff[k+1][j]){ max_diff[k+1][j] = diff; p_max[k+1][j] = i; } } } } } for(k=0; k<6; k++) for(j=0; j<5; j++){ avg_diff[k][j] /= i; } /* print statistics */ { double diff; int i, j; printf("Functional: %s\n", info->name); print_error("Avg.", "vrho", (avg_diff[0][0] + avg_diff[0][1])/2.0, NULL, NULL); j = (max_diff[0][0] > max_diff[0][1]) ? 0 : 1; get_val(xc_trial_points[p_max[0][j]], val); print_error("Max.", "vrho", max_diff[0][j], &func, val); if(info->family > XC_FAMILY_LDA){ print_error("Avg.", "vsig", (avg_diff[0][2] + avg_diff[0][3] + avg_diff[0][4])/3.0, NULL, NULL); j = (max_diff[0][2] > max_diff[0][3]) ? 2 : 3; j = (max_diff[0][j] > max_diff[0][4]) ? j : 4; get_val(xc_trial_points[p_max[0][j]], val); print_error("Max.", "vsig", max_diff[0][j], &func, val); } if(info->flags & XC_FLAGS_HAVE_FXC){ diff = avg_diff[1][0] + avg_diff[1][1] + avg_diff[2][1]; diff = diff/3.0; print_error("Avg.", "v2rho2", diff, NULL, NULL); if(max_diff[1][0] > max_diff[1][1]) {i=1; j=0;} else {i=1; j=1;} if(max_diff[2][1] > max_diff[i][j]) {i=2; j=1;} get_val(xc_trial_points[p_max[i][j]], val); print_error("Max.", "v2rho2", max_diff[i][j], &func, val); if(info->family > XC_FAMILY_LDA){ diff = avg_diff[3][0] + avg_diff[4][0] + avg_diff[5][0] + avg_diff[3][1] + avg_diff[4][1] + avg_diff[5][1]; diff = diff/6.0; print_error("Avg.", "v2rhosig", diff, NULL, NULL); if(max_diff[3][0] > max_diff[4][0]) {i=3; j=0;} else {i=4; j=0;} if(max_diff[5][0] > max_diff[i][j]) {i=5; j=0;} if(max_diff[3][1] > max_diff[i][j]) {i=3; j=1;} if(max_diff[4][1] > max_diff[i][j]) {i=4; j=1;} if(max_diff[5][1] > max_diff[i][j]) {i=5; j=1;} get_val(xc_trial_points[p_max[i][j]], val); print_error("Max.", "v2rhosig", max_diff[i][j], &func, val); diff = avg_diff[3][2] + avg_diff[4][2] + avg_diff[5][2] + avg_diff[4][3] + avg_diff[5][3] + avg_diff[5][4]; diff = diff/6.0; print_error("Avg.", "v2sig2", diff, NULL, NULL); if(max_diff[3][2] > max_diff[4][2]) {i=3; j=2;} else {i=4; j=2;} if(max_diff[5][2] > max_diff[i][j]) {i=5; j=2;} if(max_diff[4][3] > max_diff[i][j]) {i=4; j=3;} if(max_diff[5][3] > max_diff[i][j]) {i=5; j=3;} if(max_diff[5][4] > max_diff[i][j]) {i=5; j=4;} get_val(xc_trial_points[p_max[i][j]], val); print_error("Max.", "v2sig2", max_diff[i][j], &func, val); } } } xc_func_end(&func); }