![]() |
ESPResSo 3.2.0-167-g2c9ead1-git
Extensible Simulation Package for Soft Matter Research
|
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 }
1.7.5.1