Ejemplo n.º 1
0
Archivo: esp.c Proyecto: certik/openmx
void calc_esp()
{
  static int ct_AN,n1,n2,n3,po,spe;
  static int i,j,k;
  static int Rn1,Rn2,Rn3;
  static int num_grid;
  static double sum0,sum1,rij,rik;
  static double cx,cy,cz;
  static double bik,bij;
  static double x,y,z;
  static double dif,total_diff;
  static double GridVol;
  static double dx,dy,dz;
  static double dpx,dpy,dpz,tdp;
  static double tmp[4];
  static double **A,*B;
  static double *A2;
  static INTEGER N, NRHS, LDA, *IPIV, LDB, INFO;

  /* find the number of grids in the shell */
  num_grid = 0;
  for (n1=0; n1<Ngrid1; n1++){
    for (n2=0; n2<Ngrid2; n2++){
      for (n3=0; n3<Ngrid3; n3++){
        if (grid_flag[n1][n2][n3]==1) num_grid++;
      }
    }
  }

  printf("Number of grids in a van der Waals shell = %2d\n",num_grid);

  Cross_Product(gtv[2],gtv[3],tmp);
  GridVol = fabs( Dot_Product(gtv[1],tmp) );
  printf("Volume per grid = %15.10f (Bohr^3)\n",GridVol);

  /* make a matrix A and a vector B */
  A = (double**)malloc(sizeof(double*)*(atomnum+10));
  for (i=0; i<(atomnum+10); i++){
    A[i] = (double*)malloc(sizeof(double)*(atomnum+10));
    for (j=0; j<(atomnum+10); j++) A[i][j] = 0.0;
  }    

  A2 = (double*)malloc(sizeof(double)*(atomnum+10)*(atomnum+10));
  B = (double*)malloc(sizeof(double)*(atomnum+10));

  for (j=1; j<=atomnum; j++){
    for (k=1; k<=atomnum; k++){

      sum0 = 0.0;
      sum1 = 0.0;

      for (n1=0; n1<Ngrid1; n1++){
	for (n2=0; n2<Ngrid2; n2++){
	  for (n3=0; n3<Ngrid3; n3++){
	    if (grid_flag[n1][n2][n3]==1){

	      x = X_grid[n1][n2][n3];
	      y = Y_grid[n1][n2][n3];
	      z = Z_grid[n1][n2][n3];
     
              bij = 0.0;
              bik = 0.0;

              for (Rn1=-MaxRn1; Rn1<=MaxRn1; Rn1++){
                for (Rn2=-MaxRn2; Rn2<=MaxRn2; Rn2++){
                  for (Rn3=-MaxRn3; Rn3<=MaxRn3; Rn3++){

                    cx = (double)Rn1*tv[1][1] + (double)Rn2*tv[2][1] + (double)Rn3*tv[3][1]; 
                    cy = (double)Rn1*tv[1][2] + (double)Rn2*tv[2][2] + (double)Rn3*tv[3][2]; 
                    cz = (double)Rn1*tv[1][3] + (double)Rn2*tv[2][3] + (double)Rn3*tv[3][3]; 

                    /* rij */
                    dx = x - (Gxyz[j][1] + cx); 
                    dy = y - (Gxyz[j][2] + cy); 
                    dz = z - (Gxyz[j][3] + cz); 
                    rij = sqrt(dx*dx + dy*dy + dz*dz); 
                    bij += 1.0/rij;
 
		    /* rik */
		    dx = x - (Gxyz[k][1] + cx); 
		    dy = y - (Gxyz[k][2] + cy); 
		    dz = z - (Gxyz[k][3] + cz); 
		    rik = sqrt(dx*dx + dy*dy + dz*dz); 
                    bik += 1.0/rik;
                  }
                }
              }

              sum0 += bij*bik;

              if (j==1){
		
                /*
                sum1 -= (VHart[n1][n2][n3] + VNA[n1][n2][n3])*bik;
		*/

		sum1 -= VHart[n1][n2][n3]*bik;
              }

            }
	  }
	}
      }

      A[j][k] = sum0;
      if (j==1) B[k-1] = sum1;
    }
  }


  /* MK */
  if (Modified_MK==0){

    for (k=1; k<=atomnum; k++){
      A[atomnum+1][k] = 1.0;
      A[k][atomnum+1] = 1.0;
    }
    A[atomnum+1][atomnum+1] = 0.0;
    B[atomnum] = 0.0;

    /* A to A2 */

    i = 0;
    for (k=1; k<=(atomnum+1); k++){
      for (j=1; j<=(atomnum+1); j++){
	A2[i] = A[j][k];         
	i++;
      }
    }

    /* solve Aq = B */

    N = atomnum + 1;
    NRHS = 1;
    LDA = N;
    LDB = N;
    IPIV = (INTEGER*)malloc(sizeof(INTEGER)*N);

    F77_NAME(dgesv,DGESV)(&N, &NRHS, A2, &LDA, IPIV, B, &LDB, &INFO);

    if( INFO==0 ){
      printf("Success\n" ); 
    }
    else{
      printf("Failure: linear dependent\n" ); 
      exit(0); 
    }

    printf("\n");    
    for(i=0; i<atomnum; i++){
      printf("  Atom=%4d  Fitting Effective Charge=%15.11f\n",i+1,B[i]);
    }

  }

  /* Modified MK */
  else if (Modified_MK==1){

    for (k=1; k<=atomnum; k++){

      A[atomnum+1][k] = 1.0;
      A[k][atomnum+1] = 1.0;

      A[atomnum+2][k] = Gxyz[k][1];
      A[atomnum+3][k] = Gxyz[k][2];
      A[atomnum+4][k] = Gxyz[k][3];

      A[k][atomnum+2] = Gxyz[k][1];
      A[k][atomnum+3] = Gxyz[k][2];
      A[k][atomnum+4] = Gxyz[k][3];
    }

    B[atomnum  ] = 0.0;
    B[atomnum+1] = Ref_DipMx/AU2Debye;
    B[atomnum+2] = Ref_DipMy/AU2Debye;
    B[atomnum+3] = Ref_DipMz/AU2Debye;

    /* A to A2 */

    i = 0;
    for (k=1; k<=(atomnum+4); k++){
      for (j=1; j<=(atomnum+4); j++){
	A2[i] = A[j][k];         
	i++;
      }
    }

    /* solve Aq = B */

    N = atomnum + 4;
    NRHS = 1;
    LDA = N;
    LDB = N;
    IPIV = (INTEGER*)malloc(sizeof(INTEGER)*N);

    F77_NAME(dgesv,DGESV)(&N, &NRHS, A2, &LDA, IPIV, B, &LDB, &INFO); 

    if( INFO==0 ){
      printf("Success\n" ); 
    }
    else{
      printf("Failure: linear dependent\n" ); 
      exit(0); 
    }

    printf("\n");    
    for(i=0; i<atomnum; i++){
      printf("  Atom=%4d  Fitting Effective Charge=%15.11f\n",i+1,B[i]);
    }

  }

  dpx = 0.0;
  dpy = 0.0;
  dpz = 0.0;

  for (ct_AN=1; ct_AN<=atomnum; ct_AN++){
    x = Gxyz[ct_AN][1];
    y = Gxyz[ct_AN][2];
    z = Gxyz[ct_AN][3];
    dpx += AU2Debye*B[ct_AN-1]*x;
    dpy += AU2Debye*B[ct_AN-1]*y;
    dpz += AU2Debye*B[ct_AN-1]*z;
  }
  tdp = sqrt(dpx*dpx + dpy*dpy + dpz*dpz);

  printf("\n");
  printf("  Magnitude of dipole moment %15.10f (Debye)\n",tdp);
  printf("  Component x y z  %15.10f %15.10f %15.10f\n",dpx,dpy,dpz);

  /* calc diff */

  total_diff = 0.0; 

  for (n1=0; n1<Ngrid1; n1++){
    for (n2=0; n2<Ngrid2; n2++){
      for (n3=0; n3<Ngrid3; n3++){
	if (grid_flag[n1][n2][n3]==1){

          x = X_grid[n1][n2][n3];
	  y = Y_grid[n1][n2][n3];
	  z = Z_grid[n1][n2][n3];

          for (Rn1=-MaxRn1; Rn1<=MaxRn1; Rn1++){
            for (Rn2=-MaxRn2; Rn2<=MaxRn2; Rn2++){
              for (Rn3=-MaxRn3; Rn3<=MaxRn3; Rn3++){

                cx = (double)Rn1*tv[1][1] + (double)Rn2*tv[2][1] + (double)Rn3*tv[3][1]; 
                cy = (double)Rn1*tv[1][2] + (double)Rn2*tv[2][2] + (double)Rn3*tv[3][2]; 
                cz = (double)Rn1*tv[1][3] + (double)Rn2*tv[2][3] + (double)Rn3*tv[3][3]; 

                for (j=1; j<=atomnum; j++){

                  dx = x - (Gxyz[j][1] + cx); 
                  dy = y - (Gxyz[j][2] + cy); 
                  dz = z - (Gxyz[j][3] + cz); 
                  rij = sqrt(dx*dx + dy*dy + dz*dz); 

                  dif = -VHart[n1][n2][n3] + B[j-1]/rij;
                  total_diff += dif*dif;
 	        }
	      }
	    }
	  }

	}
      }
    }
  }

  total_diff = sqrt(total_diff)/(GridVol*num_grid); 
  printf("RMS between the given ESP and fitting charges (Hartree/Bohr^3)=%15.12f\n\n",
         total_diff);

  /* freeing of arrays */
  for (i=0; i<(atomnum+10); i++){
    free(A[i]);
  }    
  free(A);

  free(B);
  free(A2);
  free(IPIV);

}
// -------------------------------------------------------------------------- //
int Class_VolTri::ReturnSimplexID(
    a3vector1D  &P,
    int          S0
) {

// ========================================================================== //
// int Class_VolTri::ReturnSimplexID(                                         //
//     a3vector1D  &P,                                                        //
//     int          S0)                                                       //
//                                                                            //
// Return the ID of the simplex enclosing point P.                            //
// ========================================================================== //
// INPUT                                                                      //
// ========================================================================== //
// - P     : a3vector1D, point coordinates                                    //
// - S0    : int, seed for search procedure                                   //
// ========================================================================== //
// OUTPUT                                                                     //
// ========================================================================== //
// - S     : int, ID of simplex enclosing point P                             //
// ========================================================================== //

// ========================================================================== //
// VARIABLES DECLARATION                                                      //
// ========================================================================== //

// Local variables
bool                        check = false;
int                         n, m, p;
double                      max_dp, dp;
bvector1D                   visited(nSimplex, false);
ivector2D                   face_vlist;
a3vector1D                  x, y, xF, xS, dir;
a3vector2D                  face_normals;
LIFOstack<int>              stack;

// Counters
int                         i, j, k, l, S, A;
/*debug*/int                         n_visited = 0;

// /*debug*/ofstream       log_file;
// /*debug*/log_file.open("SEARCH.log", ifstream::app);

// ========================================================================== //
// INITIALIZE PARAMETERS                                                      //
// ========================================================================== //
// x.fill(0.0);
// y.fill(0.0);

// /*debug*/log_file << "point coordinates: " << P << endl;

// ========================================================================== //
// BUILD ADJACENCY IF NOT ALREADY BUILT                                       //
// ========================================================================== //
if ((Adjacency.size() == 0) || (Adjacency.size() < nSimplex)) {
    BuildAdjacency();
}

// ========================================================================== //
// LOOP UNTIL SIMPLEX IS FOUND                                                //
// ========================================================================== //
stack.push(S0);
while ((stack.TOPSTK > 0) && (!check)) {

// /*debug*/n_visited++;

    // Pop item from stack -------------------------------------------------- //
    S = stack.pop();
    visited[S] = true;

// /*debug*/log_file << "  traversing simplex: " << S << endl;
// /*debug*/log_file << "  (visited: " << n_visited << " of " << nSimplex << endl;

    // Simplex infos -------------------------------------------------------- //
    n = infos[e_type[S]].n_vert;
    m = infos[e_type[S]].n_faces;

    // Get face vertices ---------------------------------------------------- //
    {
        face_vlist.resize(m);
        for (j = 0; j < m; ++j) {
            face_vlist[j] = FaceVertices(S, j);
        } //next j
    }

    // Simplex baricenter --------------------------------------------------- //
    {
        xS.fill(0.0);
        for (j = 0; j < n; ++j) {
            for (l = 0; l < 3; ++l) {
                xS[l] += Vertex[Simplex[S][j]][l];
            } //next l
        } //next j
        xS = xS/((double) n);
    }

    // Compute face normals ------------------------------------------------- //
    {
        face_normals.resize(m);
        for (j = 0; j < m; ++j) {
            if (face_vlist[j].size() == 2) {
                x = Vertex[face_vlist[j][1]] - Vertex[face_vlist[j][0]];
                x[2] = 0.0;
                y[0] = 0.0;
                y[1] = 0.0;
                y[2] = 1.0;
                face_normals[j] = Cross_Product(x, y);
            }
            else {
                x = Vertex[face_vlist[j][2]] - Vertex[face_vlist[j][1]];
                y = Vertex[face_vlist[j][1]] - Vertex[face_vlist[j][0]];
                face_normals[j] = Cross_Product(x, y);
            }
            face_normals[j] = face_normals[j]/max(norm_2(face_normals[j]), 2.0e-16);
        } //next j
    }
    
    // Check if Simplex S encloses point P ---------------------------------- //
    {
        check = true;
        for (j = 0; j < m; ++j) {
            n = face_vlist[j].size();
    
            // Compute face center
            xF.fill(0.0);
            for (k = 0; k < n; ++k) {
                for (l = 0; l < 3; l++) {
                    xF[l] += Vertex[face_vlist[j][k]][l];
                } //next l
            } //next k
            xF = xF/((double) n);
    
            // Check if simplex encloses point
            dir = P - xF;
            dir = dir/max(norm_2(dir), 2.0e-16);
            check = (check && (Dot_Product(dir, face_normals[j]) <= 0.0));
        } //next j
    }

// /*debug*/log_file << "    encloses point: " << check << endl;

    // Look for best direction (Euristic search of best path) --------------- //
    // NOTES:                                                                 //
    // - modificare il criterio euristico per la scelta del path migliore     //
    //   * congiungente P-xS attraversa una faccia.                           //
    //   * distanza minima dalle facce.                                       //
    // ---------------------------------------------------------------------- //
    if (!check) {

        // local direction of searching path
        dir = P - xS;
        dir = dir/max(norm_2(dir), 2.0e-16);
    
        // Loop over simplex faces
        max_dp = -2.0;
        i = 0;
        j = -1;
        while (i < m) {
            dp = Dot_Product(face_normals[i], dir);
            if (dp > max_dp) {
                j = i;
                max_dp = dp;
            }
            i++;
        } //next i
    
        // Alternative directions
        for (i = 0; i < m; ++i) {
            A = Adjacency[S][i];
            if ((i != j) && (A >= 0) && (!visited[A])) {
                stack.push(A);
            }
        } //next i
        A = Adjacency[S][j];
        if ((A >= 0) && (!visited[A])) {
            stack.push(A);
        }
    }

} //next simplex

// /*debug*/log_file << "  (visited: " << n_visited << " of " << nSimplex << ")" << endl;

// Old algorithm ============================================================ //
{
    // while ((n_visited <= nSimplex) && (!check) && (S0 >= 0)) {
    
        // // Update simplex ID ---------------------------------------------------- //
        // // cout << "    on simplex " << S0;
        // S = S0;
        // n_visited++;
        // visited[S] = true;
        // /*debug*/log_file << "  traversing simplex: " << S << endl;
        // /*debug*/log_file << "  (visited: " << n_visited << " of " << nSimplex << endl;
    
        // // Simplex infos -------------------------------------------------------- //
        // m = infos[e_type[S]].n_faces;
        // p = infos[e_type[S]].n_vert;
    
        // // Compute simplex baricenter ------------------------------------------- //
        // {
            // xS.fill(0.0);
            // for (j = 0; j < p; ++j) {
                // for (l = 0; l < dim; ++l) {
                    // xS[l] += Vertex[Simplex[S][j]][l];
                // } //next l
            // } //next j
            // xS = xS/((double) p);
        // }
    
        // // Get face vertices ---------------------------------------------------- //
        // {
            // face_vlist.resize(m);
            // for (j = 0; j < m; ++j) {
                // face_vlist[j] = FaceVertices(S, j);
            // } //next j
        // }
    
        // // Compute face normals ------------------------------------------------- //
        // {
            // face_normals.resize(m);
            // for (j = 0; j < m; ++j) {
                // if (face_vlist[j].size() == 2) {
                    // x[0] = Vertex[face_vlist[j][1]][0] - Vertex[face_vlist[j][0]][0];
                    // x[1] = Vertex[face_vlist[j][1]][1] - Vertex[face_vlist[j][0]][1];
                    // x[2] = 0.0;
                    // y[0] = 0.0;
                    // y[1] = 0.0;
                    // y[2] = 1.0;
                    // face_normals[j] = Cross_Product(x, y);
                // }
                // else {
                    // x[0] = Vertex[face_vlist[j][2]][0] - Vertex[face_vlist[j][1]][0];
                    // x[1] = Vertex[face_vlist[j][2]][1] - Vertex[face_vlist[j][1]][1];
                    // x[2] = Vertex[face_vlist[j][2]][2] - Vertex[face_vlist[j][1]][2];
                    // y[0] = Vertex[face_vlist[j][1]][0] - Vertex[face_vlist[j][0]][0];
                    // y[1] = Vertex[face_vlist[j][1]][1] - Vertex[face_vlist[j][0]][1];
                    // y[2] = Vertex[face_vlist[j][1]][2] - Vertex[face_vlist[j][0]][2];
                    // face_normals[j] = Cross_Product(x, y);
                // }
                // face_normals[j] = face_normals[j]/max(norm_2(face_normals[j]), 2.0e-16);
            // } //next j
        // }
    
        // // Check if P is enclosed in simplex S0 --------------------------------- //
        // {
            // check = true;
            // for (j = 0; j < m; ++j) {
                // n = face_vlist[j].size();
        
                // // Compute face center
                // xF.fill(0.0);
                // for (k = 0; k < n; ++k) {
                    // for (l = 0; l < dim; l++) {
                        // xF[l] += Vertex[face_vlist[j][k]][l];
                    // } //next l
                // } //next k
                // xF = xF/((double) n);
        
                // // Check if simplex encloses point
                // for (l = 0; l < dim; l++) {
                    // dir[l] = P[l] - xF[l];
                // } //next l
                // dir = dir/max(norm_2(dir), 2.0e-16);
                // check = (check && (Dot_Product(dir, face_normals[j]) <= 0.0));
                // // cout << " f " << j << ", c: " << check;
            // } //next j
        // }
        // // cout << ", check: " << check << endl;
        // /*debug*/log_file << "    encloses point: " << check << endl;
    
        // // Look for best direction (Euristic search) ---------------------------- //
        // if (!check) {
        
            // // Find face to be crossed (Euristic search of best path)
            // {
        
                // // path local direction
                // for (l = 0; l < dim; ++l) {
                    // dir[l] = P[l] - xS[l];
                // } //next l
                // dir = dir/max(norm_2(dir), 2.0e-16);
        
                // // Loop over simplex faces
                // // WARNING: infinite loop at corner simplicies!!
                // max_dp = -2.0;
                // i = -1;
                // j = 0;
                // while (j < m) {
                    // dp = Dot_Product(face_normals[j], dir);
                    // A = Adjacency[S][j];
                    // if ((dp > max_dp) && (A >= 0)) {//&& (!visited[A])) {
                        // i = j;
                        // max_dp = dp;
                    // }
                    // j++;
                // } //next j
            // }
    
            // // Move to adjacent simplex
            // if (i >= 0) { S0 = Adjacency[S][i]; }
            // else        { S0 = -1;}
        // }
    
        // /*debug*/log_file << "    next simplex: " << S0 << endl;
    // } //next simplex
}
// /*debug*/log_file.close();

return(S); };