Beispiel #1
0
/****************************************
 Function name	  :   generate_projectors
 Description	    :
 Return type		  : void
 Author     		  : Marat Valiev
 Date & Time		  : 4/7/99 2:31:54 PM
****************************************/
void    paw_generate_projectors()
{
    int i;
    int j;
    double norm;
    double norm_error;

    if (strcmp(projector_method,"vanderbilt")==0)
    {
        paw_generate_projectors_vanderbilt();
    }
    else if (strcmp(projector_method,"blochl")==0)
    {
        paw_generate_projectors_blochl();
    }
    else
    {

        printf("error, unknown projector_method in generate_projectors \n");
        exit(1);

    }

    /*Check paw basis orthogonality*/
    norm_error = 0.0;
    for (i = 0; i <= nbasis-1; i++)
    {
        for (j = 0; j <= nbasis-1; j++)
        {

            if (orb_l[i] == orb_l[j])
            {
                norm = paw_dot_product(prj_ps[i],phi_ps[j]);

                if (i==j) norm = norm - 1.0;

                if (fabs(norm) > norm_error) norm_error=fabs(norm);


            }

        }
    }

    if (paw_debug())
        printf("paw basis is orthogonal to within %le \n",norm_error);

    projectors_done = True;
}
Beispiel #2
0
void    paw_generate_projectors_blochl()
{
    int i;
    int j;
    int k;
    int Ngrid;
    double norm;
    double max_prj;
    double max_phi;
    double max_phi_ps;
    double tmp_prj;
    double *V_ref;
    double *V;
    double *rgrid;
    double **b;
    double **L;
    double **U;
    double **L_inv;
    double **U_inv;
    double **test_matrix;
    char  output[300];
    FILE  *fp;


    /*make sure the pseudo orbitalas were found*/
    if (! pseudo_orbitals_done)
    {
        printf("cannot calculate projectors\n");
        printf("pseudo basis is not ready\n");
        exit(1);

    }

    Ngrid = paw_N_LogGrid();
    rgrid = paw_r_LogGrid();

    b = paw_alloc_2d_array(nbasis,nbasis);
    L = paw_alloc_2d_array(nbasis,nbasis);
    L_inv = paw_alloc_2d_array(nbasis,nbasis);
    U = paw_alloc_2d_array(nbasis,nbasis);
    U_inv = paw_alloc_2d_array(nbasis,nbasis);
    test_matrix = paw_alloc_2d_array(nbasis,nbasis);

    /*obtain the ref potential*/
    V_ref = paw_get_ref_pot();

    /*form initial guess for projectors as in Blochl*/
    for (i = 0; i < nbasis; ++i)
    {
        V = paw_get_paw_potential(i);

        for (k = 0; k < Ngrid; ++k)
            prj_ps[i][k] = (V_ref[k] - V[k])*phi_ps[i][k];

        if (paw_debug())
        {
            sprintf(output, "%s%s_%d%d", paw_sdir(),"p",prin_n[i],orb_l[i]);
            fp = fopen(output, "w+");
            for (k = 0; k < Ngrid; ++k)
            {
                fprintf(fp, "%le\t  %le\t %le \n", rgrid[k], prj_ps[i][k],(V_ref[k] - V[k]));
            }
            fclose(fp);
        }

    }

    /*check for accidental null projectors*/
    for (i = 0; i < nbasis; ++i)
    {

        max_prj = 0.0;

        for (k = 0; k < Ngrid; ++k)
        {
            tmp_prj = fabs(prj_ps[i][k]);
            if (tmp_prj > max_prj)
                max_prj = tmp_prj;
        }

        if (max_prj <0.000001)
        {
            printf("found null projectors, aborting the program ... \n");
            exit(1);
        }
    }





    for (i=0;i<=nbasis-1;i++)
    {
        for (j=0;j<=nbasis-1;j++)
        {
            if (orb_l[i] == orb_l[j] )
            {
                b[i][j] = paw_dot_product(phi_ps[j],prj_ps[i]);

            }
            else
            {
                b[i][j] = 0.0;
            }

        }
    }

    paw_lu_decompose(nbasis, b, L, U);
    paw_triang_matrix_inverse("l",nbasis,L,L_inv);

    paw_triang_matrix_inverse("u",nbasis,U,U_inv);

    for (i=0;i<=nbasis-1;i++)
    {
        for (k = 0; k <= Ngrid-1; k++)
            prj_ps0[i][k] = prj_ps[i][k];
    }

    for (i=0;i<=nbasis-1;i++)
    {
        paw_Zero_LogGrid(prj_ps[i]);
        paw_Zero_LogGrid(phi[i]);
        paw_Zero_LogGrid(phi_ps[i]);
        paw_Zero_LogGrid(phi_prime[i]);
        paw_Zero_LogGrid(phi_ps_prime[i]);
    }

    for (i=0;i<=nbasis-1;i++)
    {
        for (j=0;j<=i;j++)
        {

            for (k = 0; k <= Ngrid-1; k++)
            {
                prj_ps[i][k] = prj_ps[i][k] + L_inv[i][j]*prj_ps0[j][k];

                phi[i][k]          = phi[i][k]          + U_inv[j][i]*phi0[j][k];
                phi_ps[i][k]       = phi_ps[i][k]       + U_inv[j][i]*phi_ps0[j][k];
                phi_prime[i][k]    = phi_prime[i][k]    + U_inv[j][i]*phi0_prime[j][k];
                phi_ps_prime[i][k] = phi_ps_prime[i][k] + U_inv[j][i]*phi_ps0_prime[j][k];

            }


        }

    }

    for (i=0;i<=nbasis-1;i++)
        paw_Zero_LogGrid(prj_ps0[i]);

    for (i=0;i<=nbasis-1;i++)
    {
        for (j=0;j<=nbasis-1;j++)
        {

            for (k = 0; k <= Ngrid-1; k++)
            {
                prj_ps0[i][k] = prj_ps0[i][k] + U_inv[i][j]*prj_ps[j][k];

            }


        }

    }


    /*rescale basis*/
    for (i = 0; i <= nbasis-1; i++)
    {

        max_prj = 0.0;
        max_phi = 0.0;
        max_phi_ps = 0.0;

        for (k = 0; k < i_r_orbital[i]; k++)
        {
            if (max_prj < fabs(prj_ps[i][k]))
                max_prj =  fabs(prj_ps[i][k]);

            if (max_phi_ps < fabs(phi_ps[i][k]))
                max_phi_ps =  fabs(phi_ps[i][k]);

        }

        if (max_prj == 0.0 || max_phi_ps == 0.0)
        {
            printf("division by zero while rescaling basis\n");
            exit(99);
        }

        norm = 0.75*sqrt(max_phi_ps/max_prj);

        max_prj = 0.0;
        max_phi = 0.0;
        max_phi_ps = 0.0;

        scaling_factor[i] = norm;

        for (k = 0; k < Ngrid; ++k)
        {
            prj_ps[i][k]       = prj_ps[i][k]*norm;
            phi[i][k]          = phi[i][k]/norm;
            phi_ps[i][k]       = phi_ps[i][k]/norm;
            phi_prime[i][k]    = phi_prime[i][k]/norm;
            phi_ps_prime[i][k] = phi_ps_prime[i][k]/norm;

        }

    }

    for (i = 0; i <= nbasis-1; i++)
    {
        for  (j = 0; j <= nbasis-1; j++)
        {
            tr_matrix[i][j] = U_inv[i][j];
        }
    }
    if (paw_debug())
        printf("derivative=%f\n",phi_ps_prime[0][0]/(rgrid[0]*paw_log_amesh_LogGrid()));

}
Beispiel #3
0
void    paw_generate_projectors_vanderbilt()
{
    int i;
    int j;
    int k;
    int Ngrid;
    double norm;
    double max_prj;
    double max_phi;
    double max_phi_ps;
    double tmp_prj;
    double *V_ref;
    double *V;
    double *rgrid;
    double **b;
    double **prj_ps0;
    char  output[300];
    FILE  *fp;


    /*make sure the pseudo orbitalas were found*/
    if (! pseudo_orbitals_done)
    {
        printf("cannot calculate projectors\n");
        printf("pseudo basis is not ready\n");
        exit(1);

    }

    Ngrid = paw_N_LogGrid();
    rgrid = paw_r_LogGrid();

    b = paw_alloc_2d_array(nbasis,nbasis);
    prj_ps0 = paw_alloc_2d_array(nbasis,Ngrid);

    /*obtain the ref potential*/
    V_ref = paw_get_ref_pot();

    /*form initial guess for projectors as in Blochl*/
    for (i = 0; i < nbasis; ++i)
    {
        V = paw_get_paw_potential(i);

        for (k = 0; k < Ngrid; ++k)
            prj_ps[i][k] = (V_ref[k] - V[k])*phi_ps[i][k];

        if (paw_debug())
        {
            sprintf(output, "%s%s_%d%d", paw_sdir(),"p",prin_n[i],orb_l[i]);
            fp = fopen(output, "w+");
            for (k = 0; k < Ngrid; ++k)
            {
                fprintf(fp, "%le\t  %le\t %le \n", rgrid[k], prj_ps[i][k],(V_ref[k] - V[k]));
            }
            fclose(fp);
        }


    }

    /*check for accidental null projectors*/
    for (i = 0; i < nbasis; ++i)
    {

        max_prj = 0.0;

        for (k = 0; k < Ngrid; ++k)
        {
            tmp_prj = fabs(prj_ps[i][k]);
            if (tmp_prj > max_prj)
                max_prj = tmp_prj;
        }

        if (max_prj <0.000001)
        {
            printf("found null projectors, aborting the program ... \n");
            exit(1);
        }
    }





    for (i=0;i<=nbasis-1;i++)
    {
        for (j=0;j<=nbasis-1;j++)
        {
            if (orb_l[i] == orb_l[j] )
            {
                b[i][j] = paw_dot_product(phi_ps[j],prj_ps[i]);

            }
            else
            {
                b[i][j] = 0.0;
            }



        }
    }

    paw_get_inverse(b,nbasis);

    for (i=0;i<=nbasis-1;i++)
    {
        for (k = 0; k <= Ngrid-1; k++)
            prj_ps0[i][k] = prj_ps[i][k];
    }

    for (i=0;i<=nbasis-1;i++)
    {
        paw_Zero_LogGrid(prj_ps[i]);
    }

    for (i=0;i<=nbasis-1;i++)
    {
        for (j=0;j<=nbasis-1;j++)
        {

            for (k = 0; k <= Ngrid-1; k++)
                prj_ps[i][k] = prj_ps[i][k] + b[i][j]*prj_ps0[j][k];

        }

    }

    for (i=0;i<=nbasis-1;i++)
    {

        norm = paw_dot_product(prj_ps[i],phi_ps[i]);
        if (fabs(norm) < SMALL)
        {
            printf("division by zero while normalizing prj_pss");
            exit(99);
        }

        if (paw_debug()) printf("prj_ps norm=%le\n",norm);

        for (k = 0; k < Ngrid; ++k)
            prj_ps[i][k] = prj_ps[i][k]/norm;

    }

    /*rescale basis*/
    for (i = 0; i <= nbasis-1; i++)
    {

        max_prj = 0.0;
        max_phi = 0.0;
        max_phi_ps = 0.0;

        for (k = 0; k < i_r_orbital[i]; k++)
        {
            if (max_prj < fabs(prj_ps[i][k]))
                max_prj =  fabs(prj_ps[i][k]);

            if (max_phi_ps < fabs(phi_ps[i][k]))
                max_phi_ps =  fabs(phi_ps[i][k]);

        }

        if (max_prj == 0.0 || max_phi_ps == 0.0)
        {
            printf("division by zero while rescaling basis\n");
            exit(99);
        }

        norm = 0.75*sqrt(max_phi_ps/max_prj);

        max_prj = 0.0;
        max_phi = 0.0;
        max_phi_ps = 0.0;

        for (k = 0; k < Ngrid; ++k)
        {
            prj_ps[i][k]       = prj_ps[i][k]*norm;
            phi[i][k]          = phi[i][k]/norm;
            phi_ps[i][k]       = phi_ps[i][k]/norm;
            phi_prime[i][k]    = phi_prime[i][k]/norm;
            phi_ps_prime[i][k] = phi_ps_prime[i][k]/norm;

        }

    }



}
Beispiel #4
0
/****************************************
 Function name	  : paw_solve_scattering_orbitals
 Description	    :
 Return type		  : void
 Author     		  : Marat Valiev
 Date & Time		  : 4/10/99 4:58:27 PM
****************************************/
void paw_solve_scattering_orbitals()
{
    int i;
    int j;
    int k;
    int i_match;
    int Ngrid;
    double sum;
    double *V;
    double *rgrid;
    double r_sphere;
    double Zion;

    Ngrid = paw_N_LogGrid();
    rgrid = paw_r_LogGrid();
    Zion = paw_get_ion_charge();

    /*normalization sphere radius*/
    r_sphere = 2.0;

    /*check if the occupied orbitals are done*/
    if (!(occupied_orbitals_done))
    {
        printf("cannot calculate scattering orbitals\n");
        printf("calculate occupied states first\n");
    }


    /*get Kohn-Sham potential*/
    V = paw_get_kohn_sham_potential();


    for (i=Nbound;i<Ntotal;i++)
    {

        /*set the end point*/
        i_match = Ngrid-1;

        if (Solver_Type==Schrodinger)
        {
           paw_R_Schrodinger_Fixed_E(l[i],V,i_match,eigenvalue[i],psi[i],psi_prime[i]);
        }
        else
        {
           paw_R_Pauli_Fixed_E(n[i],l[i],Zion,V,i_match,eigenvalue[i],psi[i],psi_prime[i]);
        }

        for (j=0;j<i-1;j++)
        {

            if (l[i]==l[j])
            {
                sum = paw_dot_product(psi[i],psi[j]);
                for (k=0;k<Ngrid;++k)
                    psi[i][k] = psi[i][k] - sum*psi[j][k];
            }

        }

        /*normalize*/
        sum = paw_dot_product1(paw_get_grid_index(r_sphere),psi[i],psi[i]);
        sum = 1.0/sqrt(sum);

        for (k=0;k<Ngrid;++k)
        {
            psi[i][k] = psi[i][k]*sum;
            psi_prime[i][k] = psi_prime[i][k]*sum;

        }


    }

    /*debug
    printf("orthogonality\n");
    for(i=0;i<=Ntotal-1;i++)
    {
        for(j=0;j<=Ntotal-1;j++)
        {
          if(l[i]==l[j])
          {
            printf("%d\t %d\t %f\n",i,j, paw_dot_product(psi[i],psi[j]));
          }
      
        }  
     }
        exit(1);
    end debug  */
}
Beispiel #5
0
/****************************************
 Function name	  : paw_solve_unoccupied_orbitals
 Description	    :
 Return type		  : void
 Author     		  : Marat Valiev
 Date & Time		  : 4/10/99 6:13:39 PM
****************************************/
void paw_solve_unoccupied_orbitals()
{
    int i;
    int j;
    int k;
    int state;
    int Ngrid;
    int status;
    double sum;
    double *V;
    double *rgrid;
    double Zion;


    Ngrid = paw_N_LogGrid();
    rgrid = paw_r_LogGrid();
    Zion = paw_get_ion_charge();

    /*check if the occupied orbitals are done*/
    if (!(occupied_orbitals_done))
    {
        printf("cannot calculate unoccupied states\n");
        printf("calculate occupied states first\n");
    }

    /*get Kohn-Sham potential*/
    V = paw_get_kohn_sham_potential();

    for (i=Nvalence; i<= Nbound-1; i++)
    {

        state=paw_bound_state_test(l[i],V);
        if (state==0)
        {
            printf("This potential has no bound states with n=%d l=%d\n",n[i],l[i]);
            printf("please change your input file\n");
            exit(1);
        }
        else
        {
            if (Solver_Type==Schrodinger)
            {
               status = paw_R_Schrodinger(n[i],l[i],V,
                                          &eigenvalue[i],psi[i],psi_prime[i]);
            }
            else
            {
               status = paw_R_Pauli(n[i],l[i],Zion,V,
                                          &eigenvalue[i],psi[i],psi_prime[i]);
            }

        }

        if (!(status))
        {
            printf("This potential has no bound states with n=%d l=%d\n",n[i],l[i]);
            printf("please change your input file\n");
            exit(1);
        }


        /*orthogonalize to lower orbitals*/
        for (j=0;j<=i-1;j++)
        {
            if (l[i]==l[j])
            {
                sum = paw_dot_product(psi[i],psi[j]);
                for (k=0;k<=Ngrid-1;k++)
                    psi[i][k] = psi[i][k] - sum*psi[j][k];
            }

        }

        for (k=0;k<=Ngrid-1;k++)
            psi_tmp[k] = pow((psi[i][k]/rgrid[k]),2.0);

        sum = paw_Integrate_LogGrid(psi_tmp);

        for (k=0;k<=Ngrid-1;k++)
            psi[i][k]=psi[i][k]/pow(sum,0.5);
    }


}
Beispiel #6
0
/****************************************
 Function name	  :  paw_solve_occupied_orbitals
 Description	    :
 Return type		  : void
 Author     		  : Marat Valiev
 Date & Time		  : 4/10/99 6:13:22 PM
****************************************/
void   paw_solve_occupied_orbitals()
{
    int   i;
    int   j;
    int  k;
    int  it;
    int  converged;
    int   Ngrid;
    int   max_iter;
    double sum;
    double Etmp;
    double thl;
    double sn;
    double sd;
    double dr;
    double rl0;
    double rl1;
    double vn;
    double Zion;
    double *Vo;
    double *Vo1;
    double *Vi1;
    double *Vi;
    double *rgrid;

    max_iter = 100;

    Ngrid = paw_N_LogGrid();
    rgrid = paw_r_LogGrid();

    /* allocate temporary grids */
    Vi      = paw_alloc_LogGrid();
    Vo1     = paw_alloc_LogGrid();
    Vi1     = paw_alloc_LogGrid();

    /* set initial guess for KS potential as Thomas-Fermi*/
    Zion = paw_get_ion_charge();
    paw_Thomas_Fermi(Zion,Vi);

    /*initial guess for the eigenvalues*/
    paw_guess_eigenvalues(Zion,Vi);

    it = 0;
    converged = False;
    while ((!converged) && (it < max_iter))
    {

        it        = it + 1;
        converged = True;

        /* solve for each of the eigenstates */
        for (i=0; i<= Nvalence-1; i++)
        {

            Etmp = eigenvalue[i];

            if (Solver_Type==Schrodinger)
            {
               paw_R_Schrodinger(n[i],l[i],Vi,
                                 &Etmp,psi[i],psi_prime[i]);
            }
            else
            {
               paw_R_Pauli(n[i],l[i],Zion,Vi,
                           &Etmp,psi[i],psi_prime[i]);
            }

            if (fabs(eigenvalue[i] - Etmp) >1.0e-10)
                converged = False;

            eigenvalue[i]=Etmp;


            /*orthogonalize to lower orbitals*/
            for (j=0;j<=i-1;j++)
            {
                if (l[i]==l[j])
                {
                    sum = paw_dot_product(psi[i],psi[j]);
                    for (k=0;k<Ngrid;++k)
                        psi[i][k] = psi[i][k] - sum*psi[j][k];
                }

            }

            /*normalize the orbital*/
            for (k=0; k<=Ngrid-1; k++)
                psi_tmp[k] = pow((psi[i][k]/rgrid[k]),2.0);

            sum = paw_Integrate_LogGrid(psi_tmp);

            for (k=0; k<=Ngrid-1; k++)
                psi[i][k]=psi[i][k]/pow(sum,0.5);

        }

        /*get new density*/
        paw_generate_density(rho);

        /*get new potential*/
        paw_set_kohn_sham_potential(rho);
        Vo = paw_get_kohn_sham_potential();


        /*****************************************/
        /* Generate the next iteration potential */
        /* using D.G. Anderson method            */
        /*****************************************/
        thl = 0.0;
        if (it > 1)
        {
            sn = 0.0;
            sd = 0.0;

            for (k=0; k<Ngrid; ++k)
            {
                rl0 = Vo[k]  - Vi[k];
                rl1 = Vo1[k] - Vi1[k];
                dr  = rl0 - rl1;
                sn = sn + rl0*dr*(rgrid[k]*rgrid[k]);
                sd = sd +  dr*dr*(rgrid[k]*rgrid[k]);
            }


            thl = sn/sd;

        }

        for (k=0; k<=Ngrid-1; k++)
        {

            vn = (1.0-0.5)*( (1.0-thl)*Vi[k] + thl*Vi1[k] )
                 + 0.5 *( (1.0-thl)*Vo[k] + thl*Vo1[k] );
            Vi1[k] = Vi[k];
            Vo1[k] = Vo[k];
            Vi[k]  = vn;

        }


    } /* end while */

    if (!converged)
    {
        printf("Not Converged\n");
        exit(1);
    }

    occupied_orbitals_done = True;
    paw_generate_density(rho);
    paw_set_kohn_sham_potential(rho);



    /* free up temporary memory */
    paw_dealloc_LogGrid(Vi);
    paw_dealloc_LogGrid(Vo1);
    paw_dealloc_LogGrid(Vi1);

}