void Voronoi_Charge() { double time0; int Mc_AN,Gc_AN,Mh_AN,h_AN,Gh_AN; int Cwan,GNc,GRc,Nog,Nh,MN,spin; double x,y,z,dx,dy,dz,fw; double Cxyz[4]; double FuzzyW,sum0,sum1; double magx,magy,magz; double tmagx,tmagy,tmagz; double tden,tmag,theta,phi,rho,mag; double den0,den1,vol; double VC_S,T_VC0,T_VC1; double **VC,*Voronoi_Vol; double TStime,TEtime; double S_coordinate[3]; int numprocs,myid,tag=999,ID; FILE *fp_VC; char file_VC[YOUSO10]; char buf[fp_bsize]; /* setvbuf */ MPI_Status stat; MPI_Request request; /* for OpenMP */ int OMPID,Nthrds,Nprocs; MPI_Comm_size(mpi_comm_level1,&numprocs); MPI_Comm_rank(mpi_comm_level1,&myid); dtime(&TStime); if (myid==Host_ID) printf("\n<Voronoi_Charge> calculate Voronoi charges\n");fflush(stdout); /***************************************************** allocation of array *****************************************************/ VC = (double**)malloc(sizeof(double*)*4); for (spin=0; spin<4; spin++){ VC[spin] = (double*)malloc(sizeof(double)*(atomnum+1)); } Voronoi_Vol = (double*)malloc(sizeof(double)*(atomnum+1)); /***************************************************** calculation of Voronoi charge *****************************************************/ #pragma omp parallel shared(S_coordinate,GridVol,VC,Voronoi_Vol,Density_Grid,SpinP_switch,MGridListAtom,atv,CellListAtom,GridListAtom,NumOLG,WhatSpecies,M2G,Matomnum) private(OMPID,Nthrds,Nprocs,Mc_AN,Gc_AN,Cwan,sum0,sum1,vol,tden,tmagx,tmagy,tmagz,Nog,GNc,GRc,Cxyz,x,y,z,FuzzyW,MN,den0,den1,theta,phi,rho,mag,magx,magy,magz,tmag) { /* get info. on OpenMP */ OMPID = omp_get_thread_num(); Nthrds = omp_get_num_threads(); Nprocs = omp_get_num_procs(); for (Mc_AN=1+OMPID; Mc_AN<=Matomnum; Mc_AN+=Nthrds){ Gc_AN = M2G[Mc_AN]; Cwan = WhatSpecies[Gc_AN]; sum0 = 0.0; sum1 = 0.0; vol = 0.0; tden = 0.0; tmagx = 0.0; tmagy = 0.0; tmagz = 0.0; for (Nog=0; Nog<NumOLG[Mc_AN][0]; Nog++){ /* calculate fuzzy weight */ GNc = GridListAtom[Mc_AN][Nog]; GRc = CellListAtom[Mc_AN][Nog]; Get_Grid_XYZ(GNc,Cxyz); x = Cxyz[1] + atv[GRc][1]; y = Cxyz[2] + atv[GRc][2]; z = Cxyz[3] + atv[GRc][3]; FuzzyW = Fuzzy_Weight(Gc_AN,Mc_AN,0,x,y,z); /* find charge */ MN = MGridListAtom[Mc_AN][Nog]; if (SpinP_switch<=1){ den0 = Density_Grid[0][MN]; den1 = Density_Grid[1][MN]; /* sum density */ sum0 += den0*FuzzyW; sum1 += den1*FuzzyW; /* sum volume */ vol += FuzzyW; } else{ den0 = Density_Grid[0][MN]; den1 = Density_Grid[1][MN]; theta = Density_Grid[2][MN]; phi = Density_Grid[3][MN]; rho = den0 + den1; mag = den0 - den1; magx = mag*sin(theta)*cos(phi); magy = mag*sin(theta)*sin(phi); magz = mag*cos(theta); /* sum density */ tden += rho*FuzzyW; tmagx += magx*FuzzyW; tmagy += magy*FuzzyW; tmagz += magz*FuzzyW; /* sum volume */ vol += FuzzyW; } } if (SpinP_switch<=1){ VC[0][Gc_AN] = sum0*GridVol; VC[1][Gc_AN] = sum1*GridVol; } else { tmag = sqrt(tmagx*tmagx + tmagy*tmagy + tmagz*tmagz); sum0 = 0.5*(tden + tmag); sum1 = 0.5*(tden - tmag); xyz2spherical( tmagx,tmagy,tmagz, 0.0,0.0,0.0, S_coordinate ); VC[0][Gc_AN] = sum0*GridVol; VC[1][Gc_AN] = sum1*GridVol; VC[2][Gc_AN] = S_coordinate[1]; VC[3][Gc_AN] = S_coordinate[2]; } Voronoi_Vol[Gc_AN] = vol*GridVol*BohrR*BohrR*BohrR; } /* Mc_AN */ } /* #pragma omp parallel */ /***************************************************** MPI VC *****************************************************/ for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ ID = G2ID[Gc_AN]; MPI_Bcast(&VC[0][Gc_AN], 1, MPI_DOUBLE, ID, mpi_comm_level1); } for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ ID = G2ID[Gc_AN]; MPI_Bcast(&VC[1][Gc_AN], 1, MPI_DOUBLE, ID, mpi_comm_level1); } if (SpinP_switch==3){ for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ ID = G2ID[Gc_AN]; MPI_Bcast(&VC[2][Gc_AN], 1, MPI_DOUBLE, ID, mpi_comm_level1); } for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ ID = G2ID[Gc_AN]; MPI_Bcast(&VC[3][Gc_AN], 1, MPI_DOUBLE, ID, mpi_comm_level1); } } for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ ID = G2ID[Gc_AN]; MPI_Bcast(&Voronoi_Vol[Gc_AN], 1, MPI_DOUBLE, ID, mpi_comm_level1); } VC_S = 0.0; T_VC0 = 0.0; T_VC1 = 0.0; for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ VC_S += VC[0][Gc_AN] - VC[1][Gc_AN]; T_VC0 += VC[0][Gc_AN]; T_VC1 += VC[1][Gc_AN]; } /**************************************** file, *.VC ****************************************/ if ( myid==Host_ID ){ sprintf(file_VC,"%s%s.VC",filepath,filename); if ((fp_VC = fopen(file_VC,"w")) != NULL){ #ifdef xt3 setvbuf(fp_VC,buf,_IOFBF,fp_bsize); /* setvbuf */ #endif fprintf(fp_VC,"\n"); fprintf(fp_VC,"***********************************************************\n"); fprintf(fp_VC,"***********************************************************\n"); fprintf(fp_VC," Voronoi charges \n"); fprintf(fp_VC,"***********************************************************\n"); fprintf(fp_VC,"***********************************************************\n\n"); fprintf(fp_VC," Sum of Voronoi charges for up = %15.12f\n", T_VC0); fprintf(fp_VC," Sum of Voronoi charges for down = %15.12f\n", T_VC1); fprintf(fp_VC," Sum of Voronoi charges for total = %15.12f\n\n", T_VC0+T_VC1); fprintf(fp_VC," Total spin magnetic moment (muB) by Voronoi charges = %15.12f\n\n",VC_S); if (SpinP_switch<=1){ fprintf(fp_VC," Up spin Down spin Sum Diff Voronoi Volume (Ang.^3)\n"); for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ fprintf(fp_VC," Atom=%4d %12.9f %12.9f %12.9f %12.9f %12.9f\n", Gc_AN, VC[0][Gc_AN], VC[1][Gc_AN], VC[0][Gc_AN] + VC[1][Gc_AN], VC[0][Gc_AN] - VC[1][Gc_AN], Voronoi_Vol[Gc_AN]); } } else{ fprintf(fp_VC," Up spin Down spin Sum Diff Theta(Deg) Phi(Deg) Voronoi Volume (Ang.^3)\n"); for (Gc_AN=1; Gc_AN<=atomnum; Gc_AN++){ fprintf(fp_VC," Atom=%4d %12.9f %12.9f %12.9f %12.9f %8.4f %8.4f %12.9f\n", Gc_AN, VC[0][Gc_AN], VC[1][Gc_AN], VC[0][Gc_AN] + VC[1][Gc_AN], VC[0][Gc_AN] - VC[1][Gc_AN], VC[2][Gc_AN]/PI*180.0,VC[3][Gc_AN]/PI*180.0, Voronoi_Vol[Gc_AN]); } } fclose(fp_VC); } else{ printf("Failure of saving the VC file.\n"); } } /***************************************************** freeing of array *****************************************************/ for (spin=0; spin<4; spin++){ free(VC[spin]); } free(VC); free(Voronoi_Vol); /* for time */ dtime(&TEtime); time0 = TEtime - TStime; }
double Set_Aden_Grid(int init_density) { /**************************************************** Densities by the atomic superposition densities on grids ****************************************************/ static int firsttime=1; int i,k,MN,ct_AN,Gc_AN,Mc_AN,top_num; int Rn,Cwan,Nc,GNc,GRc,n,size1,size2; int My_Max,Max_Size; int size_AtomDen_Grid; double time0; double x,y,z,DenA,DenPCC,dDenA,dDenPCC; double tmp0,dx,dy,dz,r,rmin=10e-14; double Nele,Nu,Nd,M,ocupcy_u,ocupcy_d; double rho,mag,magx,magy,magz,theta,phi; double TStime,TEtime; double Cxyz[4]; double S_coordinate[3]; double *tmp_array; double *tmp_array2; double **AtomDen_Grid; double **PCCDen_Grid; double *AtomDen2_Grid; double *PCCDen2_Grid; int *Snd_Size,*Rcv_Size; int numprocs,myid,tag=999,ID,IDS,IDR; double Stime_atom, Etime_atom; double Nup,Ndown,sit,cot,sip,cop; dcomplex U[2][2]; MPI_Status stat; MPI_Request request; /* for OpenMP */ int OMPID,Nthrds,Nprocs; /* MPI */ MPI_Comm_size(mpi_comm_level1,&numprocs); MPI_Comm_rank(mpi_comm_level1,&myid); dtime(&TStime); /**************************************************** allocation of arrays: int Snd_Size[numprocs] int Rcv_Size[numprocs] double AtomDen_Grid[Matomnum+MatomnumF+1] [GridN_Atom[Gc_AN]] double PCCDen_Grid[Matomnum+MatomnumF+1] [GridN_Atom[Gc_AN]] ****************************************************/ Snd_Size = (int*)malloc(sizeof(int)*numprocs); Rcv_Size = (int*)malloc(sizeof(int)*numprocs); size_AtomDen_Grid = Matomnum+MatomnumF+1; AtomDen_Grid = (double**)malloc(sizeof(double*)*(Matomnum+MatomnumF+1)); AtomDen_Grid[0] = (double*)malloc(sizeof(double)*1); for (Mc_AN=1; Mc_AN<=(Matomnum+MatomnumF); Mc_AN++){ Gc_AN = F_M2G[Mc_AN]; AtomDen_Grid[Mc_AN] = (double*)malloc(sizeof(double)*GridN_Atom[Gc_AN]); size_AtomDen_Grid += GridN_Atom[Gc_AN]; } PCCDen_Grid = (double**)malloc(sizeof(double*)*(Matomnum+MatomnumF+1)); PCCDen_Grid[0] = (double*)malloc(sizeof(double)*1); for (Mc_AN=1; Mc_AN<=(Matomnum+MatomnumF); Mc_AN++){ Gc_AN = F_M2G[Mc_AN]; PCCDen_Grid[Mc_AN] = (double*)malloc(sizeof(double)*GridN_Atom[Gc_AN]); } /* PrintMemory */ if (firsttime==1){ PrintMemory("Set_Aden_Grid: AtomDen_Grid", sizeof(double)*size_AtomDen_Grid, NULL); PrintMemory("Set_Aden_Grid: PCCDen_Grid", sizeof(double)*size_AtomDen_Grid, NULL); firsttime = 0; } /****************************************************** setting of AtomDen_Grid ******************************************************/ /************************************** for spin non-collinear 1. set rho, mx, my, mz 2. calculate theta and phi 3. n_up = (rho+m)/2 n_dn = (rho-m)/2 **************************************/ if (SpinP_switch==3){ for (MN=0; MN<My_NumGrid1; MN++){ Density_Grid[0][MN] = 0.0; Density_Grid[1][MN] = 0.0; Density_Grid[2][MN] = 0.0; Density_Grid[3][MN] = 0.0; ADensity_Grid[MN] = 0.0; } } /* spin collinear */ else{ for (MN=0; MN<My_NumGrid1; MN++){ Density_Grid[0][MN] = 0.0; Density_Grid[1][MN] = 0.0; ADensity_Grid[MN] = 0.0; } } /* PCC */ if (PCC_switch==1) { for (MN=0; MN<My_NumGrid1; MN++){ PCCDensity_Grid[MN] = 0.0; } } for (Mc_AN=1; Mc_AN<=Matomnum; Mc_AN++){ dtime(&Stime_atom); Gc_AN = M2G[Mc_AN]; Cwan = WhatSpecies[Gc_AN]; #pragma omp parallel shared(PCCDen_Grid,PCC_switch,AtomDen_Grid,Cwan,Gxyz,atv,Mc_AN,CellListAtom,GridListAtom,GridN_Atom,Gc_AN) private(OMPID,Nthrds,Nprocs,Nc,GNc,GRc,Cxyz,dx,dy,dz,r,DenA) { /* get info. on OpenMP */ OMPID = omp_get_thread_num(); Nthrds = omp_get_num_threads(); Nprocs = omp_get_num_procs(); for (Nc=OMPID*GridN_Atom[Gc_AN]/Nthrds; Nc<(OMPID+1)*GridN_Atom[Gc_AN]/Nthrds; Nc++){ GNc = GridListAtom[Mc_AN][Nc]; GRc = CellListAtom[Mc_AN][Nc]; Get_Grid_XYZ(GNc,Cxyz); dx = Cxyz[1] + atv[GRc][1] - Gxyz[Gc_AN][1]; dy = Cxyz[2] + atv[GRc][2] - Gxyz[Gc_AN][2]; dz = Cxyz[3] + atv[GRc][3] - Gxyz[Gc_AN][3]; r = sqrt(dx*dx + dy*dy + dz*dz); /* AtomicDenF */ DenA = AtomicDenF(Cwan,r); AtomDen_Grid[Mc_AN][Nc] = DenA; /* partial core correction */ if (PCC_switch==1) { PCCDen_Grid[Mc_AN][Nc] = AtomicPCCF(Cwan,r); } } } /* #pragma omp parallel */ dtime(&Etime_atom); time_per_atom[Gc_AN] += Etime_atom - Stime_atom; } /****************************************************** MPI: AtomDen_Grid ******************************************************/ /* find data size for sending and recieving */ tag = 999; My_Max = -10000; for (ID=0; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (ID!=0){ /* sending size */ if (F_Snd_Num[IDS]!=0){ /* find data size */ size1 = 0; for (n=0; n<F_Snd_Num[IDS]; n++){ Gc_AN = Snd_GAN[IDS][n]; size1 += GridN_Atom[Gc_AN]; } Snd_Size[IDS] = size1; MPI_Isend(&size1, 1, MPI_INT, IDS, tag, mpi_comm_level1, &request); } else{ Snd_Size[IDS] = 0; } /* receiving size */ if (F_Rcv_Num[IDR]!=0){ MPI_Recv(&size2, 1, MPI_INT, IDR, tag, mpi_comm_level1, &stat); Rcv_Size[IDR] = size2; } else{ Rcv_Size[IDR] = 0; } if (F_Snd_Num[IDS]!=0) MPI_Wait(&request,&stat); } else{ Snd_Size[IDS] = 0; Rcv_Size[IDR] = 0; } if (My_Max<Snd_Size[IDS]) My_Max = Snd_Size[IDS]; if (My_Max<Rcv_Size[IDR]) My_Max = Rcv_Size[IDR]; } MPI_Allreduce(&My_Max, &Max_Size, 1, MPI_INT, MPI_MAX, mpi_comm_level1); tmp_array = (double*)malloc(sizeof(double)*Max_Size); tmp_array2 = (double*)malloc(sizeof(double)*Max_Size); /* send and recieve AtomDen_Grid */ tag = 999; for (ID=0; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (ID!=0){ /***************************** sending of data *****************************/ if (F_Snd_Num[IDS]!=0){ /* find data size */ size1 = Snd_Size[IDS]; /* multidimentional array to vector array */ k = 0; for (n=0; n<F_Snd_Num[IDS]; n++){ Mc_AN = Snd_MAN[IDS][n]; Gc_AN = Snd_GAN[IDS][n]; for (i=0; i<GridN_Atom[Gc_AN]; i++){ tmp_array[k] = AtomDen_Grid[Mc_AN][i]; k++; } } /* MPI_Isend */ MPI_Isend(&tmp_array[0], size1, MPI_DOUBLE, IDS, tag, mpi_comm_level1, &request); } /***************************** receiving of block data *****************************/ if (F_Rcv_Num[IDR]!=0){ /* find data size */ size2 = Rcv_Size[IDR]; /* MPI_Recv */ MPI_Recv(&tmp_array2[0], size2, MPI_DOUBLE, IDR, tag, mpi_comm_level1, &stat); k = 0; Mc_AN = F_TopMAN[IDR] - 1; for (n=0; n<F_Rcv_Num[IDR]; n++){ Mc_AN++; Gc_AN = Rcv_GAN[IDR][n]; for (i=0; i<GridN_Atom[Gc_AN]; i++){ AtomDen_Grid[Mc_AN][i] = tmp_array2[k]; k++; } } } if (F_Snd_Num[IDS]!=0) MPI_Wait(&request,&stat); } } /****************************************************** MPI: PCCDen_Grid ******************************************************/ /* send and receive PCCDen_Grid */ tag = 999; for (ID=0; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (ID!=0){ /***************************** sending of data *****************************/ if (F_Snd_Num[IDS]!=0){ /* find data size */ size1 = Snd_Size[IDS]; /* multidimentional array to vector array */ k = 0; for (n=0; n<F_Snd_Num[IDS]; n++){ Mc_AN = Snd_MAN[IDS][n]; Gc_AN = Snd_GAN[IDS][n]; for (i=0; i<GridN_Atom[Gc_AN]; i++){ tmp_array[k] = PCCDen_Grid[Mc_AN][i]; k++; } } /* MPI_Isend */ MPI_Isend(&tmp_array[0], size1, MPI_DOUBLE, IDS, tag, mpi_comm_level1, &request); } /***************************** receiving of block data *****************************/ if (F_Rcv_Num[IDR]!=0){ /* find data size */ size2 = Rcv_Size[IDR]; /* MPI_Recv */ MPI_Recv(&tmp_array2[0], size2, MPI_DOUBLE, IDR, tag, mpi_comm_level1, &stat); k = 0; Mc_AN = F_TopMAN[IDR] - 1; for (n=0; n<F_Rcv_Num[IDR]; n++){ Mc_AN++; Gc_AN = Rcv_GAN[IDR][n]; for (i=0; i<GridN_Atom[Gc_AN]; i++){ PCCDen_Grid[Mc_AN][i] = tmp_array2[k]; k++; } } } if (F_Snd_Num[IDS]!=0) MPI_Wait(&request,&stat); } } /**************************************************** freeing of arrays: tmp_array tmp_array2 ****************************************************/ free(tmp_array); free(tmp_array2); /****************************************************** superposition of atomic densities ******************************************************/ for (Mc_AN=1; Mc_AN<=(Matomnum+MatomnumF); Mc_AN++){ dtime(&Stime_atom); Gc_AN = F_M2G[Mc_AN]; Cwan = WhatSpecies[Gc_AN]; Nele = fabs(InitN_USpin[Gc_AN] + InitN_DSpin[Gc_AN]); Nu = InitN_USpin[Gc_AN]; Nd = InitN_DSpin[Gc_AN]; if (1.0e-15<Nele){ ocupcy_u = Nu/Nele; ocupcy_d = Nd/Nele; } else{ ocupcy_u = 0.0; ocupcy_d = 0.0; } if (2<=level_stdout){ printf(" Mc_AN=%3d Gc_AN=%3d ocupcy_u=%15.12f ocupcy_d=%15.12f\n", Mc_AN,Gc_AN,ocupcy_u,ocupcy_d); } for (Nc=0; Nc<GridN_Atom[Gc_AN]; Nc++){ MN = MGridListAtom[Mc_AN][Nc]; if (0<=MN){ DenA = AtomDen_Grid[Mc_AN][Nc]; /* spin collinear */ if ( init_density==1 && SpinP_switch==1 ){ Density_Grid[0][MN] += ocupcy_u*DenA; Density_Grid[1][MN] += ocupcy_d*DenA; } /* spin non-collinear */ else if ( init_density==1 && SpinP_switch==3 ){ theta = Angle0_Spin[Gc_AN]; phi = Angle1_Spin[Gc_AN]; rho = DenA; mag = (ocupcy_u - ocupcy_d)*DenA; magx = mag*sin(theta)*cos(phi); magy = mag*sin(theta)*sin(phi); magz = mag*cos(theta); Density_Grid[0][MN] += rho; Density_Grid[1][MN] += magx; Density_Grid[2][MN] += magy; Density_Grid[3][MN] += magz; } else if (init_density==1){ Density_Grid[0][MN] += 0.5*DenA; } else{ ADensity_Grid[MN] += DenA; } /* partial core correction */ if (PCC_switch==1) { DenPCC = PCCDen_Grid[Mc_AN][Nc]; /* later add this in Set_XC_Grid */ PCCDensity_Grid[MN] += 0.5*DenPCC; } } } dtime(&Etime_atom); time_per_atom[Gc_AN] += Etime_atom - Stime_atom; } /****************************************************** atomic densities (AtomDen2_Grid) in terms of FNAN2 ******************************************************/ AtomDen2_Grid = (double*)malloc(sizeof(double)*FNAN2_Grid); /* MPI */ tag = 999; for (ID=0; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (ID!=0){ /***************************** sending of data *****************************/ if (Num_Snd_FNAN2_Grid[IDS]!=0){ tmp_array = (double*)malloc(sizeof(double)*Num_Snd_FNAN2_Grid[IDS]); /* vector array */ for (i=0; i<Num_Snd_FNAN2_Grid[IDS]; i++){ Gc_AN = Snd_FNAN2_At[IDS][i]; Mc_AN = F_G2M[Gc_AN]; Nc = Snd_FNAN2_Nc[IDS][i]; tmp_array[i] = AtomDen_Grid[Mc_AN][Nc]; } /* MPI_Isend */ MPI_Isend(&tmp_array[0], Num_Snd_FNAN2_Grid[IDS], MPI_DOUBLE, IDS, tag, mpi_comm_level1, &request); } /***************************** receiving of data *****************************/ if (Num_Rcv_FNAN2_Grid[IDR]!=0){ top_num = TopMAN2_Grid[IDR]; /* MPI_Recv */ MPI_Recv(&AtomDen2_Grid[top_num], Num_Rcv_FNAN2_Grid[IDR], MPI_DOUBLE, IDR, tag, mpi_comm_level1, &stat); } if (Num_Snd_FNAN2_Grid[IDS]!=0){ MPI_Wait(&request,&stat); free(tmp_array); } } } /* Density_Grid += AtomDen2_Grid */ for (i=0; i<FNAN2_Grid; i++){ DenA = AtomDen2_Grid[i]; MN = Rcv_FNAN2_MN[i]; Gc_AN = Rcv_FNAN2_GA[i]; Nele = InitN_USpin[Gc_AN] + InitN_DSpin[Gc_AN]; Nu = InitN_USpin[Gc_AN]; Nd = InitN_DSpin[Gc_AN]; if (1.0e-13<Nele){ ocupcy_u = Nu/Nele; ocupcy_d = Nd/Nele; } else{ ocupcy_u = 0.0; ocupcy_d = 0.0; } /* spin collinear */ if ( init_density==1 && SpinP_switch==1 ){ Density_Grid[0][MN] += ocupcy_u*DenA; Density_Grid[1][MN] += ocupcy_d*DenA; } /* spin non-collinear */ else if ( init_density==1 && SpinP_switch==3 ){ theta = Angle0_Spin[Gc_AN]; phi = Angle1_Spin[Gc_AN]; rho = DenA; mag = (ocupcy_u - ocupcy_d)*DenA; magx = mag*sin(theta)*cos(phi); magy = mag*sin(theta)*sin(phi); magz = mag*cos(theta); Density_Grid[0][MN] += rho; Density_Grid[1][MN] += magx; Density_Grid[2][MN] += magy; Density_Grid[3][MN] += magz; } else if (init_density==1){ Density_Grid[0][MN] += 0.5*DenA; } } /****************************************************** pcc densities (PCCDen2_Grid) in terms of FNAN2 ******************************************************/ PCCDen2_Grid = (double*)malloc(sizeof(double)*FNAN2_Grid); if (PCC_switch==1) { /* MPI */ tag = 999; for (ID=0; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (ID!=0){ /***************************** sending of data *****************************/ if (Num_Snd_FNAN2_Grid[IDS]!=0){ tmp_array = (double*)malloc(sizeof(double)*Num_Snd_FNAN2_Grid[IDS]); /* vector array */ for (i=0; i<Num_Snd_FNAN2_Grid[IDS]; i++){ Gc_AN = Snd_FNAN2_At[IDS][i]; Mc_AN = F_G2M[Gc_AN]; Nc = Snd_FNAN2_Nc[IDS][i]; tmp_array[i] = PCCDen_Grid[Mc_AN][Nc]; } /* MPI_Isend */ MPI_Isend(&tmp_array[0], Num_Snd_FNAN2_Grid[IDS], MPI_DOUBLE, IDS, tag, mpi_comm_level1, &request); } /***************************** receiving of data *****************************/ if (Num_Rcv_FNAN2_Grid[IDR]!=0){ top_num = TopMAN2_Grid[IDR]; /* MPI_Recv */ MPI_Recv(&PCCDen2_Grid[top_num], Num_Rcv_FNAN2_Grid[IDR], MPI_DOUBLE, IDR, tag, mpi_comm_level1, &stat); } if (Num_Snd_FNAN2_Grid[IDS]!=0){ MPI_Wait(&request,&stat); free(tmp_array); } } } /* PCCDensity_Grid += PCCDen2_Grid */ for (i=0; i<FNAN2_Grid; i++){ MN = Rcv_FNAN2_MN[i]; PCCDensity_Grid[MN] += 0.5*PCCDen2_Grid[i]; } } /**************************************************** initialize diagonal and off-diagonal densities in case of spin non-collinear DFT ****************************************************/ if (init_density==1 && SpinP_switch==3){ for (MN=0; MN<My_NumGrid1; MN++){ rho = Density_Grid[0][MN]; magx = Density_Grid[1][MN]; magy = Density_Grid[2][MN]; magz = Density_Grid[3][MN]; Density_Grid[0][MN] = 0.5*(rho + magz); Density_Grid[1][MN] = 0.5*(rho - magz); Density_Grid[2][MN] = 0.5*magx; Density_Grid[3][MN] =-0.5*magy; } } /****************************************************** Density_Grid to ADensity_Grid ******************************************************/ if ( init_density==1 && (SpinP_switch==1 || SpinP_switch==3) ){ for (MN=0; MN<My_NumGrid1; MN++){ ADensity_Grid[MN] = Density_Grid[0][MN] + Density_Grid[1][MN]; } } else if (init_density==1){ for (MN=0; MN<My_NumGrid1; MN++){ ADensity_Grid[MN] = 2.0*Density_Grid[0][MN]; } } /**************************************************** in case of non-spin polarization up-spin to down-spin ****************************************************/ if (init_density==1 && SpinP_switch==0){ for (MN=0; MN<My_NumGrid1; MN++){ Density_Grid[1][MN] = Density_Grid[0][MN]; } } /**************************************************** freeing of arrays: Snd_Size Rcv_Size AtomDen_Grid PCCDen_Grid ****************************************************/ free(Snd_Size); free(Rcv_Size); for (Mc_AN=0; Mc_AN<=(Matomnum+MatomnumF); Mc_AN++){ free(AtomDen_Grid[Mc_AN]); } free(AtomDen_Grid); for (Mc_AN=0; Mc_AN<=(Matomnum+MatomnumF); Mc_AN++){ free(PCCDen_Grid[Mc_AN]); } free(PCCDen_Grid); free(AtomDen2_Grid); free(PCCDen2_Grid); /* elapsed time */ dtime(&TEtime); time0 = TEtime - TStime; return time0; }
void TRAN_Set_Electrode_Grid(MPI_Comm comm1, int *TRAN_Poisson_flag2, double *Grid_Origin, /* origin of the grid */ double tv[4][4], /* unit vector of the cell*/ double Left_tv[4][4], /* unit vector left */ double Right_tv[4][4], /* unit vector right */ double gtv[4][4], /* unit vector of the grid point, which is gtv*integer */ int Ngrid1, int Ngrid2, int Ngrid3 /* # of c grid points */ ) { int l1[2]; int i,j,k,k2,k3; int tnoA,tnoB,wanB,wanA; int GA_AN,MA_AN,Nc,GNc,LB_AN_e; int GB_AN; int Rn_e,GA_AN_e,GB_AN_e,GRc; int side,direction; int spin,p2,p3; int n1,n2,n3; int id,gidx; double rcutA,rcutB,r,r1,r2; double dx,dy,dz,xx; double dx1,dy1,dz1; double dx2,dy2,dz2; double x1,y1,z1; double x2,y2,z2; double sum,tmp; double offset[4]; double R[4]; double xyz[4]; double *Chi0,*Chi1,*Chi2; int idim=1; int myid; fftw_complex *in, *out; fftw_plan p; MPI_Comm_rank(comm1, &myid); /* for passing TRAN_Poisson_flag to "DFT" */ *TRAN_Poisson_flag2 = TRAN_Poisson_flag; if (myid==Host_ID) { printf("<TRAN_Set_Electrode_Grid>\n"); } /* allocation of array */ Chi0 = (double*)malloc(sizeof(double)*List_YOUSO[7]); Chi1 = (double*)malloc(sizeof(double)*List_YOUSO[7]); Chi2 = (double*)malloc(sizeof(double)*List_YOUSO[7]); in = fftw_malloc(sizeof(fftw_complex)*List_YOUSO[17]); out = fftw_malloc(sizeof(fftw_complex)*List_YOUSO[17]); /* allocation of arrays */ if (print_stdout) { printf("%d %d %d %d %d\n",Ngrid1,Ngrid2,Ngrid3,TRAN_grid_bound[0], TRAN_grid_bound[1]); } for (side=0; side<2; side++) { ElectrodeDensity_Grid[side] = (double**)malloc(sizeof(double*)*(SpinP_switch_e[side]+1)); } /* left lead */ side = 0; l1[0] = 0; l1[1] = TRAN_grid_bound[0]; for (spin=0; spin<=SpinP_switch_e[side]; spin++) { ElectrodeDensity_Grid[side][spin] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); } ElectrodeADensity_Grid[side] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); ElectrodedVHart_Grid[side] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); VHart_Boundary[side] = (dcomplex***)malloc(sizeof(dcomplex**)*Ngrid1_e[side]); for (n1=0; n1<Ngrid1_e[side]; n1++) { VHart_Boundary[side][n1] = (dcomplex**)malloc(sizeof(dcomplex*)*Ngrid2); for (n2=0; n2<Ngrid2; n2++) { VHart_Boundary[side][n1][n2] = (dcomplex*)malloc(sizeof(dcomplex)*Ngrid3); } } /* right lead */ side = 1; l1[0] = TRAN_grid_bound[1]; l1[1] = Ngrid1 - 1; for (spin=0; spin<=SpinP_switch_e[side]; spin++) { ElectrodeDensity_Grid[side][spin] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); } ElectrodeADensity_Grid[side] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); ElectrodedVHart_Grid[side] = (double*)malloc(sizeof(double)*Ngrid3*Ngrid2*(l1[1]-l1[0]+1)); VHart_Boundary[side] = (dcomplex***)malloc(sizeof(dcomplex**)*Ngrid1_e[side]); for (n1=0; n1<Ngrid1_e[side]; n1++) { VHart_Boundary[side][n1] = (dcomplex**)malloc(sizeof(dcomplex*)*Ngrid2); for (n2=0; n2<Ngrid2; n2++) { VHart_Boundary[side][n1][n2] = (dcomplex*)malloc(sizeof(dcomplex)*Ngrid3); } } /******************************************************* charge density contributed by the left and right sides *******************************************************/ for (side=0; side<=1; side++) { if (side==0) { direction = -1; l1[0] = 0; l1[1] = TRAN_grid_bound[0]; } else { direction = 1; l1[0] = TRAN_grid_bound[1]; l1[1] = Ngrid1-1; } /* initialize ElectrodeDensity_Grid and ElectrodeADensity_Grid */ for (spin=0; spin<=SpinP_switch_e[side]; spin++) { for (i=0; i<Ngrid3*Ngrid2*(l1[1]-l1[0]+1); i++) { ElectrodeDensity_Grid[side][spin][i] = 0.0; } } for (i=0; i<Ngrid3*Ngrid2*(l1[1]-l1[0]+1); i++) { ElectrodeADensity_Grid[side][i] = 0.0; } /* calculate charge density */ for (n1=l1[0]; n1<=l1[1]; n1++) { for (n2=0; n2<Ngrid2; n2++) { for (n3=0; n3<Ngrid3; n3++) { GNc = n1*Ngrid2*Ngrid3 + n2*Ngrid3 + n3; Get_Grid_XYZ(GNc, xyz); for (p2=-1; p2<=1; p2++) { for (p3=-1; p3<=1; p3++) { for (GA_AN_e=1; GA_AN_e<=atomnum_e[side]; GA_AN_e++) { if (side==0) GA_AN = GA_AN_e; else GA_AN = GA_AN_e + Latomnum + Catomnum; wanA = WhatSpecies[GA_AN]; tnoA = Spe_Total_CNO[wanA]; rcutA = Spe_Atom_Cut1[wanA]; x1 = Gxyz[GA_AN][1] + (double)direction*tv_e[side][1][1] + (double)p2*tv_e[side][2][1] + (double)p3*tv_e[side][3][1]; y1 = Gxyz[GA_AN][2] + (double)direction*tv_e[side][1][2] + (double)p2*tv_e[side][2][2] + (double)p3*tv_e[side][3][2]; z1 = Gxyz[GA_AN][3] + (double)direction*tv_e[side][1][3] + (double)p2*tv_e[side][2][3] + (double)p3*tv_e[side][3][3]; dx1 = xyz[1] - x1; dy1 = xyz[2] - y1; dz1 = xyz[3] - z1; r1 = sqrt(dx1*dx1 + dy1*dy1 + dz1*dz1); if (r1<=rcutA) { /****************************** ElectrodeDensity_Grid ******************************/ Get_Orbitals(wanA,dx1,dy1,dz1,Chi1); for (LB_AN_e=0; LB_AN_e<=FNAN_e[side][GA_AN_e]; LB_AN_e++) { GB_AN_e = natn_e[side][GA_AN_e][LB_AN_e]; Rn_e = ncn_e[side][GA_AN_e][LB_AN_e]; if (side==0) GB_AN = GB_AN_e; else GB_AN = GB_AN_e + Latomnum + Catomnum; wanB = WhatSpecies[GB_AN]; tnoB = Spe_Total_CNO[wanB]; rcutB = Spe_Atom_Cut1[wanB]; x2 = Gxyz[GB_AN][1] + (double)(direction+atv_ijk_e[side][Rn_e][1])*tv_e[side][1][1] + (double)(p2 +atv_ijk_e[side][Rn_e][2])*tv_e[side][2][1] + (double)(p3 +atv_ijk_e[side][Rn_e][3])*tv_e[side][3][1]; y2 = Gxyz[GB_AN][2] + (double)(direction+atv_ijk_e[side][Rn_e][1])*tv_e[side][1][2] + (double)(p2 +atv_ijk_e[side][Rn_e][2])*tv_e[side][2][2] + (double)(p3 +atv_ijk_e[side][Rn_e][3])*tv_e[side][3][2]; z2 = Gxyz[GB_AN][3] + (double)(direction+atv_ijk_e[side][Rn_e][1])*tv_e[side][1][3] + (double)(p2 +atv_ijk_e[side][Rn_e][2])*tv_e[side][2][3] + (double)(p3 +atv_ijk_e[side][Rn_e][3])*tv_e[side][3][3]; dx2 = xyz[1] - x2; dy2 = xyz[2] - y2; dz2 = xyz[3] - z2; r2 = sqrt(dx2*dx2 + dy2*dy2 + dz2*dz2); if (r2<=rcutB) { Get_Orbitals(wanB,dx2,dy2,dz2,Chi2); for (spin=0; spin<=SpinP_switch; spin++) { if (atv_ijk_e[side][Rn_e][1]==(-direction)) { sum = 0.0; for (i=0; i<tnoA; i++) { for (j=0; j<tnoB; j++) { /* revised by Y. Xiao for Noncollinear NEGF calculations */ /* sum += 2.0*DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; */ if(spin==3) { sum -= 2.0*DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; } else { sum += 2.0*DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; } /* until here by Y. Xiao for Noncollinear NEGF calculations */ } } } else if (atv_ijk_e[side][Rn_e][1]==0) { sum = 0.0; for (i=0; i<tnoA; i++) { for (j=0; j<tnoB; j++) { /* revised by Y. Xiao for Noncollinear NEGF calculations */ /* sum += DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; */ if(spin==3) { sum -= DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; } else { sum += DM_e[side][0][spin][GA_AN_e][LB_AN_e][i][j]*Chi1[i]*Chi2[j]; } /* until here by Y. Xiao for Noncollinear NEGF calculations */ } } } gidx = (n1-l1[0])*Ngrid2*Ngrid3 + n2*Ngrid3 + n3; ElectrodeDensity_Grid[side][spin][gidx] += sum; } } } /****************************** ElectrodeADensity_Grid ******************************/ xx = 0.5*log(dx1*dx1 + dy1*dy1 + dz1*dz1); gidx = (n1-l1[0])*Ngrid2*Ngrid3 + n2*Ngrid3 + n3; ElectrodeADensity_Grid[side][gidx] += 0.5*KumoF( Spe_Num_Mesh_PAO[wanA], xx, Spe_PAO_XV[wanA], Spe_PAO_RV[wanA], Spe_Atomic_Den[wanA]); } /* if (r1<=rcutA) */ } } } } } } } /* side */ /******************************************************* 2D FFT of dDen_Grid_e, which is difference between charge density calculated by KS wave functions and the superposition of atomic charge density, of the left and right leads on the bc plane for TRAN_Poisson *******************************************************/ for (side=0; side<=1; side++) { /* set VHart_Boundary in real space */ for (n1=0; n1<Ngrid1_e[side]; n1++) { for (n2=0; n2<Ngrid2; n2++) { for (n3=0; n3<Ngrid3; n3++) { /* borrow the array "VHart_Boundary" */ VHart_Boundary[side][n1][n2][n3].r = dDen_Grid_e[side][n1*Ngrid2*Ngrid3+n2*Ngrid3+n3]; VHart_Boundary[side][n1][n2][n3].i = 0.0; } } } /* FFT of VHart_Boundary for c-axis */ p = fftw_plan_dft_1d(Ngrid3,in,out,-1,FFTW_ESTIMATE); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (n2=0; n2<Ngrid2; n2++) { for (n3=0; n3<Ngrid3; n3++) { in[n3][0] = VHart_Boundary[side][n1][n2][n3].r; in[n3][1] = VHart_Boundary[side][n1][n2][n3].i; } fftw_execute(p); for (k3=0; k3<Ngrid3; k3++) { VHart_Boundary[side][n1][n2][k3].r = out[k3][0]; VHart_Boundary[side][n1][n2][k3].i = out[k3][1]; } } } fftw_destroy_plan(p); /* FFT of VHart_Boundary for b-axis */ p = fftw_plan_dft_1d(Ngrid2,in,out,-1,FFTW_ESTIMATE); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (k3=0; k3<Ngrid3; k3++) { for (n2=0; n2<Ngrid2; n2++) { in[n2][0] = VHart_Boundary[side][n1][n2][k3].r; in[n2][1] = VHart_Boundary[side][n1][n2][k3].i; } fftw_execute(p); for (k2=0; k2<Ngrid2; k2++) { VHart_Boundary[side][n1][k2][k3].r = out[k2][0]; VHart_Boundary[side][n1][k2][k3].i = out[k2][1]; } } } fftw_destroy_plan(p); tmp = 1.0/(double)(Ngrid2*Ngrid3); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (k2=0; k2<Ngrid2; k2++) { for (k3=0; k3<Ngrid3; k3++) { VHart_Boundary[side][n1][k2][k3].r *= tmp; VHart_Boundary[side][n1][k2][k3].i *= tmp; } } } } /* side */ /******************************************************* interpolation of 2D Fourier transformed difference charge of the left and right leads on the bc plane for TRAN_Poisson_FFT_Extended *******************************************************/ { int ip,Num; double x; double *vr,*vi,*xg; if (1.0<fabs(tv[1][1])) ip = 1; else if (1.0<fabs(tv[1][2])) ip = 2; else if (1.0<fabs(tv[1][3])) ip = 3; side = 0; IntNgrid1_e[side] = (int)(fabs((double)TRAN_FFTE_CpyNum*tv_e[side][1][ip]+1.0e-8)/length_gtv[1]); dDen_IntBoundary[side] = (dcomplex***)malloc(sizeof(dcomplex**)*IntNgrid1_e[side]); for (n1=0; n1<IntNgrid1_e[side]; n1++) { dDen_IntBoundary[side][n1] = (dcomplex**)malloc(sizeof(dcomplex*)*Ngrid2); for (n2=0; n2<Ngrid2; n2++) { dDen_IntBoundary[side][n1][n2] = (dcomplex*)malloc(sizeof(dcomplex)*Ngrid3); } } side = 1; IntNgrid1_e[side] = (int)(fabs((double)TRAN_FFTE_CpyNum*tv_e[side][1][ip]+1.0e-8)/length_gtv[1]); dDen_IntBoundary[side] = (dcomplex***)malloc(sizeof(dcomplex**)*IntNgrid1_e[side]); for (n1=0; n1<IntNgrid1_e[side]; n1++) { dDen_IntBoundary[side][n1] = (dcomplex**)malloc(sizeof(dcomplex*)*Ngrid2); for (n2=0; n2<Ngrid2; n2++) { dDen_IntBoundary[side][n1][n2] = (dcomplex*)malloc(sizeof(dcomplex)*Ngrid3); } } for (side=0; side<=1; side++) { vr = (double*)malloc(sizeof(double)*(TRAN_FFTE_CpyNum+2)*Ngrid1_e[side]); vi = (double*)malloc(sizeof(double)*(TRAN_FFTE_CpyNum+2)*Ngrid1_e[side]); xg = (double*)malloc(sizeof(double)*(TRAN_FFTE_CpyNum+2)*Ngrid1_e[side]); for (k2=0; k2<Ngrid2; k2++) { for (k3=0; k3<Ngrid3; k3++) { /* set up the 1D data */ for (i=0; i<(TRAN_FFTE_CpyNum+2); i++) { for (n1=0; n1<Ngrid1_e[side]; n1++) { vr[n1+i*Ngrid1_e[side]] = VHart_Boundary[side][n1][k2][k3].r; vi[n1+i*Ngrid1_e[side]] = VHart_Boundary[side][n1][k2][k3].i; } for (n1=0; n1<Ngrid1_e[side]; n1++) { xg[n1+i*Ngrid1_e[side]] = (double)(n1+i*Ngrid1_e[side])*fabs(tv_e[side][1][ip]/(double)Ngrid1_e[side]) - (double)(Ngrid1_e[side]*(TRAN_FFTE_CpyNum+1))*fabs(tv_e[side][1][ip]/(double)Ngrid1_e[side]) + Grid_Origin[ip]; } } /* if (myid==0 && side==0 && k2==1 && k3==0){ for (n1=0; n1<Ngrid1_e[side]*(TRAN_FFTE_CpyNum+2); n1++){ printf("A %15.12f %15.12f %15.12f\n",xg[n1],vr[n1],vi[n1]); } } */ /* interpolation */ for (n1=0; n1<IntNgrid1_e[side]; n1++) { x = (double)n1*length_gtv[1] - (double)IntNgrid1_e[side]*length_gtv[1] + Grid_Origin[ip]; dDen_IntBoundary[side][n1][k2][k3].r = Interpolated_Func(x, xg, vr, (TRAN_FFTE_CpyNum+2)*Ngrid1_e[side]); dDen_IntBoundary[side][n1][k2][k3].i = Interpolated_Func(x, xg, vi, (TRAN_FFTE_CpyNum+2)*Ngrid1_e[side]); /* if (myid==0 && side==0 && k2==1 && k3==0){ printf("B %15.12f %15.12f %15.12f\n", x,dDen_IntBoundary[side][n1][k2][k3].r, dDen_IntBoundary[side][n1][k2][k3].i); } */ } } } free(xg); free(vi); free(vr); } } /**************************************************** 2D FFT of dVHartree of the left and right leads on the bc plane for TRAN_Poisson ****************************************************/ for (side=0; side<=1; side++) { /* set VHart_Boundary in real space */ for (n1=0; n1<Ngrid1_e[side]; n1++) { for (n2=0; n2<Ngrid2; n2++) { for (n3=0; n3<Ngrid3; n3++) { VHart_Boundary[side][n1][n2][n3].r = dVHart_Grid_e[side][n1*Ngrid2*Ngrid3+n2*Ngrid3+n3]; VHart_Boundary[side][n1][n2][n3].i = 0.0; } } } /* FFT of VHart_Boundary for c-axis */ p = fftw_plan_dft_1d(Ngrid3,in,out,-1,FFTW_ESTIMATE); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (n2=0; n2<Ngrid2; n2++) { for (n3=0; n3<Ngrid3; n3++) { in[n3][0] = VHart_Boundary[side][n1][n2][n3].r; in[n3][1] = VHart_Boundary[side][n1][n2][n3].i; } fftw_execute(p); for (k3=0; k3<Ngrid3; k3++) { VHart_Boundary[side][n1][n2][k3].r = out[k3][0]; VHart_Boundary[side][n1][n2][k3].i = out[k3][1]; } } } fftw_destroy_plan(p); /* FFT of VHart_Boundary for b-axis */ p = fftw_plan_dft_1d(Ngrid2,in,out,-1,FFTW_ESTIMATE); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (k3=0; k3<Ngrid3; k3++) { for (n2=0; n2<Ngrid2; n2++) { in[n2][0] = VHart_Boundary[side][n1][n2][k3].r; in[n2][1] = VHart_Boundary[side][n1][n2][k3].i; } fftw_execute(p); for (k2=0; k2<Ngrid2; k2++) { VHart_Boundary[side][n1][k2][k3].r = out[k2][0]; VHart_Boundary[side][n1][k2][k3].i = out[k2][1]; } } } fftw_destroy_plan(p); tmp = 1.0/(double)(Ngrid2*Ngrid3); for (n1=0; n1<Ngrid1_e[side]; n1++) { for (k2=0; k2<Ngrid2; k2++) { for (k3=0; k3<Ngrid3; k3++) { VHart_Boundary[side][n1][k2][k3].r *= tmp; VHart_Boundary[side][n1][k2][k3].i *= tmp; } } } } /* side */ /* freeing of arrays */ free(Chi0); free(Chi1); free(Chi2); fftw_free(in); fftw_free(out); }
void Make_VNA_Grid() { static int firsttime=1; unsigned long long int n2D,N2D,GNc,GN; int i,Mc_AN,Gc_AN,BN,CN,LN,GRc,N3[4]; int AN,Nc,MN,Cwan,NN_S,NN_R; int size_AtomVNA_Grid; int size_AtomVNA_Snd_Grid_A2B; int size_AtomVNA_Rcv_Grid_A2B; double Cxyz[4]; double r,dx,dy,dz; double **AtomVNA_Grid; double **AtomVNA_Snd_Grid_A2B; double **AtomVNA_Rcv_Grid_A2B; double Stime_atom, Etime_atom; int numprocs,myid,tag=999,ID,IDS,IDR; int OMPID,Nthrds,Nprocs; MPI_Status stat; MPI_Request request; MPI_Status *stat_send; MPI_Status *stat_recv; MPI_Request *request_send; MPI_Request *request_recv; /* MPI */ MPI_Comm_size(mpi_comm_level1,&numprocs); MPI_Comm_rank(mpi_comm_level1,&myid); /* allocation of arrays */ size_AtomVNA_Grid = 1; AtomVNA_Grid = (double**)malloc(sizeof(double*)*(Matomnum+1)); AtomVNA_Grid[0] = (double*)malloc(sizeof(double)*1); for (Mc_AN=1; Mc_AN<=Matomnum; Mc_AN++){ Gc_AN = F_M2G[Mc_AN]; AtomVNA_Grid[Mc_AN] = (double*)malloc(sizeof(double)*GridN_Atom[Gc_AN]); size_AtomVNA_Grid += GridN_Atom[Gc_AN]; } size_AtomVNA_Snd_Grid_A2B = 0; AtomVNA_Snd_Grid_A2B = (double**)malloc(sizeof(double*)*numprocs); for (ID=0; ID<numprocs; ID++){ AtomVNA_Snd_Grid_A2B[ID] = (double*)malloc(sizeof(double)*Num_Snd_Grid_A2B[ID]); size_AtomVNA_Snd_Grid_A2B += Num_Snd_Grid_A2B[ID]; } size_AtomVNA_Rcv_Grid_A2B = 0; AtomVNA_Rcv_Grid_A2B = (double**)malloc(sizeof(double*)*numprocs); for (ID=0; ID<numprocs; ID++){ AtomVNA_Rcv_Grid_A2B[ID] = (double*)malloc(sizeof(double)*Num_Rcv_Grid_A2B[ID]); size_AtomVNA_Rcv_Grid_A2B += Num_Rcv_Grid_A2B[ID]; } /* PrintMemory */ if (firsttime) { PrintMemory("Set_Vpot: AtomVNA_Grid",sizeof(double)*size_AtomVNA_Grid,NULL); PrintMemory("Set_Vpot: AtomVNA_Snd_Grid_A2B",sizeof(double)*size_AtomVNA_Snd_Grid_A2B,NULL); PrintMemory("Set_Vpot: AtomVNA_Rcv_Grid_A2B",sizeof(double)*size_AtomVNA_Rcv_Grid_A2B,NULL); } /* calculation of AtomVNA_Grid */ for (MN=0; MN<My_NumGridC; MN++) VNA_Grid[MN] = 0.0; for (Mc_AN=1; Mc_AN<=Matomnum; Mc_AN++){ dtime(&Stime_atom); Gc_AN = M2G[Mc_AN]; Cwan = WhatSpecies[Gc_AN]; #pragma omp parallel shared(AtomVNA_Grid,GridN_Atom,atv,Gxyz,Gc_AN,Cwan,Mc_AN,GridListAtom,CellListAtom) private(OMPID,Nthrds,Nprocs,Nc,GNc,GRc,Cxyz,dx,dy,dz,r) { OMPID = omp_get_thread_num(); Nthrds = omp_get_num_threads(); Nprocs = omp_get_num_procs(); for (Nc=OMPID*GridN_Atom[Gc_AN]/Nthrds; Nc<(OMPID+1)*GridN_Atom[Gc_AN]/Nthrds; Nc++){ GNc = GridListAtom[Mc_AN][Nc]; GRc = CellListAtom[Mc_AN][Nc]; Get_Grid_XYZ(GNc,Cxyz); dx = Cxyz[1] + atv[GRc][1] - Gxyz[Gc_AN][1]; dy = Cxyz[2] + atv[GRc][2] - Gxyz[Gc_AN][2]; dz = Cxyz[3] + atv[GRc][3] - Gxyz[Gc_AN][3]; r = sqrt(dx*dx + dy*dy + dz*dz); AtomVNA_Grid[Mc_AN][Nc] = VNAF(Cwan,r); } #pragma omp flush(AtomVNA_Grid) } /* #pragma omp parallel */ dtime(&Etime_atom); time_per_atom[Gc_AN] += Etime_atom - Stime_atom; } /* Mc_AN */ /****************************************************** MPI communication from the partitions A to B ******************************************************/ /* copy AtomVNA_Grid to AtomVNA_Snd_Grid_A2B */ for (ID=0; ID<numprocs; ID++) Num_Snd_Grid_A2B[ID] = 0; N2D = Ngrid1*Ngrid2; for (Mc_AN=1; Mc_AN<=Matomnum; Mc_AN++){ Gc_AN = M2G[Mc_AN]; for (AN=0; AN<GridN_Atom[Gc_AN]; AN++){ GN = GridListAtom[Mc_AN][AN]; GN2N(GN,N3); n2D = N3[1]*Ngrid2 + N3[2]; ID = (int)(n2D*(unsigned long long int)numprocs/N2D); AtomVNA_Snd_Grid_A2B[ID][Num_Snd_Grid_A2B[ID]] = AtomVNA_Grid[Mc_AN][AN]; Num_Snd_Grid_A2B[ID]++; } } /* MPI: A to B */ request_send = malloc(sizeof(MPI_Request)*NN_A2B_S); request_recv = malloc(sizeof(MPI_Request)*NN_A2B_R); stat_send = malloc(sizeof(MPI_Status)*NN_A2B_S); stat_recv = malloc(sizeof(MPI_Status)*NN_A2B_R); NN_S = 0; NN_R = 0; tag = 999; for (ID=1; ID<numprocs; ID++){ IDS = (myid + ID) % numprocs; IDR = (myid - ID + numprocs) % numprocs; if (Num_Snd_Grid_A2B[IDS]!=0){ MPI_Isend(&AtomVNA_Snd_Grid_A2B[IDS][0], Num_Snd_Grid_A2B[IDS], MPI_DOUBLE, IDS, tag, mpi_comm_level1, &request_send[NN_S]); NN_S++; } if (Num_Rcv_Grid_A2B[IDR]!=0){ MPI_Irecv( &AtomVNA_Rcv_Grid_A2B[IDR][0], Num_Rcv_Grid_A2B[IDR], MPI_DOUBLE, IDR, tag, mpi_comm_level1, &request_recv[NN_R]); NN_R++; } } if (NN_S!=0) MPI_Waitall(NN_S,request_send,stat_send); if (NN_R!=0) MPI_Waitall(NN_R,request_recv,stat_recv); free(request_send); free(request_recv); free(stat_send); free(stat_recv); /* for myid */ for (i=0; i<Num_Rcv_Grid_A2B[myid]; i++){ AtomVNA_Rcv_Grid_A2B[myid][i] = AtomVNA_Snd_Grid_A2B[myid][i]; } /****************************************************** superposition of VNA in the partition B ******************************************************/ /* initialize VNA_Grid_B */ for (BN=0; BN<My_NumGridB_AB; BN++) VNA_Grid_B[BN] = 0.0; /* superposition of VNA */ for (ID=0; ID<numprocs; ID++){ for (LN=0; LN<Num_Rcv_Grid_A2B[ID]; LN++){ BN = Index_Rcv_Grid_A2B[ID][3*LN+0]; VNA_Grid_B[BN] += AtomVNA_Rcv_Grid_A2B[ID][LN]; } /* LN */ } /* ID */ /****************************************************** MPI: from the partitions B to C ******************************************************/ Data_Grid_Copy_B2C_1( VNA_Grid_B, VNA_Grid ); /* freeing of arrays */ for (Mc_AN=0; Mc_AN<=Matomnum; Mc_AN++){ free(AtomVNA_Grid[Mc_AN]); } free(AtomVNA_Grid); for (ID=0; ID<numprocs; ID++){ free(AtomVNA_Snd_Grid_A2B[ID]); } free(AtomVNA_Snd_Grid_A2B); for (ID=0; ID<numprocs; ID++){ free(AtomVNA_Rcv_Grid_A2B[ID]); } free(AtomVNA_Rcv_Grid_A2B); }