Exemple #1
0
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;

}
Exemple #2
0
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);
}
Exemple #4
0
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);
}