/**************************************** 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; }
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())); }
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; } } }
/**************************************** 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 */ }
/**************************************** 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); } }
/**************************************** 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); }