ESPResSo 3.2.0-167-g2c9ead1-git
Extensible Simulation Package for Soft Matter Research
grid.c
Go to the documentation of this file.
00001 /*
00002   Copyright (C) 2010,2011,2012,2013 The ESPResSo project
00003   Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 
00004     Max-Planck-Institute for Polymer Research, Theory Group
00005   
00006   This file is part of ESPResSo.
00007   
00008   ESPResSo is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   ESPResSo is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
00020 */
00021 /** \file grid.c   Domain decomposition for parallel computing.
00022  *
00023  *  For more information on the domain decomposition, 
00024  *  see \ref grid.h "grid.h". 
00025 */
00026 #include <mpi.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <math.h>
00031 #include "utils.h"
00032 #include "grid.h"
00033 #include "communication.h"
00034 #include "verlet.h"
00035 #include "cells.h"
00036 #include "interaction_data.h"
00037 
00038 /************************************************
00039  * defines
00040  ************************************************/    
00041 
00042 #define MAX_INTERACTION_RANGE 1e100
00043 
00044 /**********************************************
00045  * variables
00046  **********************************************/
00047 
00048 int node_grid[3] = { 0, 0, 0};
00049 int node_pos[3] = {-1,-1,-1};
00050 int node_neighbors[6] = {0, 0, 0, 0, 0, 0};
00051 int boundary[6]   = {0, 0, 0, 0, 0, 0};
00052 int periodic  = 7;
00053 
00054 double box_l[3]       = {1, 1, 1};
00055 double box_l_i[3]     = {1, 1, 1};
00056 double min_box_l;
00057 double local_box_l[3] = {1, 1, 1};
00058 double min_local_box_l;
00059 double my_left[3]     = {0, 0, 0};
00060 double my_right[3]    = {1, 1, 1};
00061 
00062 /************************************************************/
00063 
00064 void init_node_grid()
00065 {
00066   grid_changed_n_nodes();
00067   cells_on_geometry_change(CELL_FLAG_GRIDCHANGED);
00068 }
00069 
00070 int node_grid_is_set()
00071 {
00072   return (node_grid[0] > 0);
00073 }
00074 
00075 int map_position_node_array(double pos[3])
00076 {
00077   int i, im[3]={0,0,0};
00078   double f_pos[3];
00079 
00080   for (i = 0; i < 3; i++)
00081     f_pos[i] = pos[i];
00082   
00083   fold_position(f_pos, im);
00084 
00085   for (i = 0; i < 3; i++) {
00086     im[i] = (int)floor(node_grid[i]*f_pos[i]*box_l_i[i]);
00087     if (im[i] < 0)
00088       im[i] = 0;
00089     else if (im[i] >= node_grid[i])
00090       im[i] = node_grid[i] - 1;
00091   }
00092 
00093   return map_array_node(im);
00094 }
00095 
00096 void calc_node_neighbors(int node)
00097 {
00098   int dir;
00099   
00100   map_node_array(node,node_pos);
00101   for(dir=0;dir<3;dir++) {
00102     int buf;
00103     MPI_Cart_shift(comm_cart, dir, -1, &buf, node_neighbors + 2*dir);
00104     MPI_Cart_shift(comm_cart, dir, 1, &buf, node_neighbors + 2*dir + 1);
00105 
00106     /* left boundary ? */
00107     if (node_pos[dir] == 0) {
00108       boundary[2*dir] = 1;
00109     }
00110     else {
00111       boundary[2*dir] = 0;
00112     }
00113     /* right boundary ? */
00114    if (node_pos[dir] == node_grid[dir]-1) {
00115       boundary[2*dir+1] = -1;
00116     }
00117     else {
00118       boundary[2*dir+1] = 0;
00119     }
00120   }
00121   GRID_TRACE(printf("%d: node_grid %d %d %d, pos %d %d %d, node_neighbors ", this_node, node_grid[0], node_grid[1], node_grid[2], node_pos[0], node_pos[1], node_pos[2]));
00122 }
00123 
00124 void grid_changed_box_l()
00125 {
00126   int i;
00127 
00128   GRID_TRACE(fprintf(stderr,"%d: grid_changed_box_l:\n",this_node));
00129   GRID_TRACE(fprintf(stderr,"%d: node_pos %d %d %d\n", this_node, node_pos[0], node_pos[1], node_pos[2]));
00130   GRID_TRACE(fprintf(stderr,"%d: node_grid %d %d %d\n", this_node, node_grid[0], node_grid[1], node_grid[2]));
00131   for(i = 0; i < 3; i++) {
00132     local_box_l[i] = box_l[i]/(double)node_grid[i]; 
00133     my_left[i]   = node_pos[i]    *local_box_l[i];
00134     my_right[i]  = (node_pos[i]+1)*local_box_l[i];    
00135     box_l_i[i] = 1/box_l[i];
00136   }
00137 
00138   calc_minimal_box_dimensions();
00139 
00140 #ifdef GRID_DEBUG
00141   fprintf(stderr,"%d: local_box_l = (%.3f, %.3f, %.3f)\n",this_node,
00142           local_box_l[0],local_box_l[1],local_box_l[2]);
00143   fprintf(stderr,"%d: coordinates: x in [%.3f, %.3f], y in [%.3f, %.3f], z in [%.3f, %.3f]\n",this_node,
00144           my_left[0],my_right[0],my_left[1],my_right[1],my_left[2],my_right[2]);
00145 #endif
00146 }
00147 
00148 void grid_changed_n_nodes()
00149 {
00150   int per[3] = { 1, 1, 1 };
00151   GRID_TRACE(fprintf(stderr,"%d: grid_changed_n_nodes:\n",this_node));
00152 
00153   MPI_Comm_free(&comm_cart);
00154   
00155   MPI_Cart_create(MPI_COMM_WORLD, 3, node_grid, per, 0, &comm_cart);
00156 
00157   MPI_Comm_rank(comm_cart, &this_node);
00158 
00159   MPI_Cart_coords(comm_cart, this_node, 3, node_pos);
00160 
00161   calc_node_neighbors(this_node);
00162 
00163 #ifdef GRID_DEBUG
00164   fprintf(stderr,"%d: node_pos=(%d,%d,%d)\n",this_node,node_pos[0],node_pos[1],node_pos[2]);
00165   fprintf(stderr,"%d: node_neighbors=(%d,%d,%d,%d,%d,%d)\n",this_node,
00166           node_neighbors[0],node_neighbors[1],node_neighbors[2],
00167           node_neighbors[3],node_neighbors[4],node_neighbors[5]);
00168   fprintf(stderr,"%d: boundary=(%d,%d,%d,%d,%d,%d)\n",this_node,
00169           boundary[0],boundary[1],boundary[2],boundary[3],boundary[4],boundary[5]);
00170 #endif
00171 
00172   grid_changed_box_l();
00173 }
00174 
00175 void calc_minimal_box_dimensions()
00176 {
00177   int i;
00178   min_box_l = 2*MAX_INTERACTION_RANGE;
00179   min_local_box_l = MAX_INTERACTION_RANGE;
00180   for(i=0;i<3;i++) {
00181     min_box_l       = dmin(min_box_l, box_l[i]);
00182     min_local_box_l = dmin(min_local_box_l, local_box_l[i]);
00183   }
00184 }
00185 
00186 void calc_2d_grid(int n, int grid[3])
00187 {
00188   int i;
00189   i = (int)sqrt((double)n);
00190   while(i>=1) {
00191     if(n%i==0) { grid[0] = n/i; grid[1] = i; grid[2] = 1; return; }
00192     i--;
00193   }
00194 }
00195 
00196 int map_3don2d_grid(int g3d[3],int g2d[3], int mult[3])
00197 {
00198   int i,row_dir=-1;
00199   /* trivial case */
00200   if(g3d[2]==1) { 
00201     for(i=0;i<3;i++) mult[i]=1;
00202     return 2;
00203   }
00204   if(g2d[0]%g3d[0] == 0) {
00205     if(g2d[1]%g3d[1] == 0) {row_dir=2; }
00206     else if(g2d[1]%g3d[2] == 0) {row_dir=1; g2d[2]=g2d[1]; g2d[1]=1; }
00207   }
00208   else if(g2d[0]%g3d[1] == 0) {
00209     if(g2d[1]%g3d[0]==0) {row_dir=2; i=g2d[0]; g2d[0]=g2d[1]; g2d[1]=i; }
00210     else if(g2d[1]%g3d[2]==0) {row_dir=0; g2d[2]=g2d[1]; g2d[1]=g2d[0]; g2d[0]=1; }
00211   }
00212   else if(g2d[0]%g3d[2] == 0) {
00213     if(g2d[1]%g3d[0]==0) {row_dir=1; g2d[2]=g2d[0]; g2d[0]=g2d[1]; g2d[1]=1; }
00214     else if(g2d[1]%g3d[1]==0) {row_dir=0; g2d[2]=g2d[0]; g2d[0]=1; }
00215   }
00216   for(i=0;i<3;i++) mult[i]=g2d[i]/g3d[i];
00217   return row_dir;
00218 }
00219 
00220 void rescale_boxl(int dir, double d_new) {
00221   double scale = (dir-3) ? d_new/box_l[dir] : d_new/box_l[0];
00222   if (scale < 1.) {
00223     mpi_rescale_particles(dir,scale);
00224     if (dir < 3) 
00225       box_l[dir] = d_new;
00226     else
00227       box_l[0] = box_l[1] = box_l[2] = d_new;
00228     mpi_bcast_parameter(FIELD_BOXL);
00229   }
00230   else if (scale > 1.) {
00231     if (dir < 3) 
00232       box_l[dir] = d_new;
00233     else
00234       box_l[0] = box_l[1] = box_l[2] = d_new;
00235     mpi_bcast_parameter(FIELD_BOXL);
00236     mpi_rescale_particles(dir,scale);
00237   }
00238 }