void solve_RelTroullier (int num_psp, int *n_psp, int *l_psp, int *s_psp, double *e_psp, double *fill_psp, double *rcut_psp, double **r_psi_psp, double **r_psi_prime_psp, double *rho_psp, double *rho_semicore, double **V_psp, double *eall_psp, double *eh_psp, double *ph_psp, double *ex_psp, double *px_psp, double *ec_psp, double *pc_psp) { int istate, i, l, k, p, s2, match, mch, Ngrid; double al, amesh, rmax, Zion; double gamma, gpr, nu0; double ldpsi_match; double el, eeig=0.0; double ph, px, pc, eh, ex, ec; double *ul, *ul_prime; double *wl, *wl_prime; double *r, *Vh, *Vx, *Vc, *rho_total, *Vall, *Vl; /* Allocate Grids */ Vall = Vall_Atom (); r = r_LogGrid (); Ngrid = N_LogGrid (); al = log_amesh_LogGrid (); amesh = amesh_LogGrid (); Zion = 0.0; for (k = 0; k < Ngrid; ++k) rho_psp[k] = 0.0; if (debug_print ()) { printf ("\n\nRelTroullier pseudopotential check\n\n"); printf ("l\trcore rmatch E in E psp norm test slope test\n"); } for (p = 0; p < (num_psp); ++p) { l = l_psp[p]; s2 = s_psp[p]; wl = r_psi_psp[p]; wl_prime = r_psi_prime_psp[p]; Vl = V_psp[p]; /*******************************************/ /* Solve for scattering state if necessary */ /*******************************************/ if (fill_psp[p] < 1.e-15) { rmax = 10.0; solve_Scattering_State_Atom (n_psp[p], l_psp[p], e_psp[p], rmax); /* scattering state saved at the end of the atom list */ istate = Nvalence_Atom () + Ncore_Atom (); if (s2 < 0) istate += 1; mch = (int) rint (log (rmax / r[0]) / al); ul = r_psi_Atom (istate); ul_prime = r_psi_prime_Atom (istate); nu0 = Norm_LogGrid (mch, (l + 1.0), ul); nu0 = 1.0 / sqrt (nu0); for (i = 0; i < Ngrid; ++i) { ul[i] = ul[i] * nu0; ul_prime[i] = ul_prime[i] * nu0; } } /*******************************************/ /* find state of all-electron wavefunction */ /*******************************************/ else istate = state_RelAtom (n_psp[p], l_psp[p], s_psp[p]); /*************************************/ /* get the all-electron wavefunction */ /*************************************/ ul = r_psi_Atom (istate); ul_prime = r_psi_prime_Atom (istate); el = e_psp[p]; /*****************************/ /* find matching point stuff */ /*****************************/ match = (int) rint (log (rcut_psp[p] / r[0]) / al); ldpsi_match = ul_prime[match] / ul[match]; /* make sure that wavefunctions are non-negative at the matching point */ if (ul[match] < 0.0) { nu0 = -1.0; for (i = 0; i < Ngrid; ++i) { ul[i] = ul[i] * nu0; ul_prime[i] = ul_prime[i] * nu0; } } /**************************************/ /* generate troullier pseudopotential */ /**************************************/ init_xpansion (l, match, fill_psp[p], el, Vall, ul, ul_prime, Vl, wl, wl_prime); psi_xpansion (); dpsi_xpansion (); psp_xpansion (); /******************/ /* verify psp Vl */ /******************/ /*******************/ /* psp bound state */ /*******************/ if (fill_psp[p] > 1.e-14) { R_Schrodinger (l_psp[p] + 1, l_psp[p], Vl, &mch, &el, wl, wl_prime); } /* scattering state */ else { R_Schrodinger_Fixed_Logderiv (l_psp[p] + 1, l_psp[p], Vl, match, ldpsi_match, &el, wl, wl_prime); R_Schrodinger_Fixed_E (l_psp[p] + 1, l_psp[p], Vl, Ngrid - 1, el, wl, wl_prime); /* normalize the scattering state to mch = 10.0 a.u. */ rmax = 10.0; mch = rint (log (rmax / r[0]) / al); nu0 = Norm_LogGrid (mch, (l + 1.0), wl); nu0 = 1.0 / sqrt (nu0); for (i = 0; i < Ngrid; ++i) { wl[i] = wl[i] * nu0; wl_prime[i] = wl_prime[i] * nu0; } } gamma = fabs (ul[match] / wl[match]); gpr = fabs (ul_prime[match] / wl_prime[match]); if (debug_print ()) { /*printf("ul[match] wl[match]: %lf %lf\n",ul[match],wl[match]); */ printf ("%d\t%lf %lf %lf %lf %lf %lf\n", l_psp[p], rcut_psp[p], r[match], e_psp[p], el, gamma, gpr); } /* Use the analytic form of pseudopotential */ el = e_psp[p]; psi_xpansion (); dpsi_xpansion (); psp_xpansion (); if (fill_psp[p] > 1.e-14) { eeig += fill_psp[p] * el; /* accumulate charges */ Zion += fill_psp[p]; for (k = 0; k < Ngrid; ++k) rho_psp[k] += fill_psp[p] * pow (wl[k] / r[k], 2.0); } } /* for p */ /***************************************/ /* get the hartree potential an energy */ /* get the exchange potential and energy */ /* get the correlation potential and energy */ /***************************************/ Vh = alloc_LogGrid (); Vx = alloc_LogGrid (); Vc = alloc_LogGrid (); ph = R_Hartree_DFT (rho_psp, Zion, Vh); eh = 0.5 * ph; rho_total = alloc_LogGrid (); for (k = 0; k < Ngrid; ++k) rho_total[k] = rho_psp[k] + rho_semicore[k]; R_Exchange_DFT (rho_total, Vx, &ex, &px); R_Correlation_DFT (rho_total, Vc, &ec, &pc); /* recalculate px and pc */ for (k = 0; k < Ngrid; ++k) rho_total[k] = (rho_psp[k]) * Vx[k]; px = Integrate_LogGrid (rho_total); for (k = 0; k < Ngrid; ++k) rho_total[k] = (rho_psp[k]) * Vc[k]; pc = Integrate_LogGrid (rho_total); *eall_psp = eeig + eh + ex + ec - ph - px - pc; *eh_psp = eh; *ph_psp = ph; *ex_psp = ex; *px_psp = px; *ec_psp = ec; *pc_psp = pc; for (p = 0; p < num_psp; ++p) for (k = 0; k < Ngrid; ++k) V_psp[p][k] = V_psp[p][k] - Vh[k] - Vx[k] - Vc[k]; /* deallocate memory */ dealloc_LogGrid (Vh); dealloc_LogGrid (Vx); dealloc_LogGrid (Vc); dealloc_LogGrid (rho_total); } /* solve_Troullier */
double get_c0_c12(double gamma) { int i,j,k,iteration; int indx_rc,factor; double delta; double ddelta; double tolerance, fdnew,fdold; double psp_core_charge; double constraint; double b[5],a[25]; c[0] = delta = 0.0; /* c0 coefficient */ c[1] = gamma; /* c2 coefficient */ fdold = 0.0; fdnew = 0.0; tolerance = 1.0; iteration = 0; while ((tolerance > SMALL) && ( iteration <= 50)) { ++iteration; b[0] = poly[0] - 1.0*gamma*rc[2] - delta; b[1] = poly[1] - 2.0*gamma*rc[1]; b[2] = poly[2] - 2.0*gamma; b[3] = poly[3]; b[4] = poly[4]; /* set up a matrix */ for (i=0; i<5; ++i) for (j=0; j<5; ++j) { indx_rc = 2*(j+2)-i; factor = 1; for (k=2*(j+2); k>(indx_rc); --k) factor *= k; if (indx_rc >= 0) a[i+j*5] = factor*rc[indx_rc]; else a[i+j*5] = 0.0; } gaussj(5,a,1,b); c[2] = b[0]; /* c4 coefficient */ c[3] = b[1]; /* c6 coefficient */ c[4] = b[2]; /* c8 coefficient */ c[5] = b[3]; /* c10 coefficient */ c[6] = b[4]; /* c12 coefficient */ /* generate pseudowavefunction neglecting exp(delta)=exp(c0) */ psi_xpansion(); /* Calculate the psp core charge */ psp_core_charge = Norm_LogGrid(match,l+1.0,wl); if (psp_core_charge<0.0) psp_core_charge=fabs(psp_core_charge); /* calculate new delta */ fdold = fdnew; fdnew = log(ae_core_charge/psp_core_charge) - 2.0*delta; tolerance = fabs(fdnew); if (iteration == 1) ddelta = -0.5; else ddelta = -fdnew*ddelta/(fdnew-fdold); delta = delta + ddelta; } /* while find delta */ c[0] = delta; /* error - too many iterations */ if (iteration > 200) { printf("Error in get_c0_c12: delta loop \n"); exit(98); } /* constraint = c2^2 + (2*l+5)*c4 = 0 */ constraint = 8.0*(c[1]*c[1] + (2.0*l+5.0)*c[2]); return constraint; } /* get_c0_c12 */