Exemplo n.º 1
0
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 */
Exemplo n.º 2
0
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 */