/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! FMS is distributed in the hope that it will be useful, !! !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! !! GNU General Public License for more details. !! !! !! !! You should have received a copy of the GNU General Public License !! !! along with FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* **** MppDomain.cpp **** MppDomain package NOTE: only mpi is implemented here. if needed, shmem version will be added on in the future. Contact: Zhi.Liang@noaa.gov */ #include #include #include "mpp.h" #include "mpp_domain.h" /*********************************************************** global variables ***********************************************************/ int pe, npes, root_pe; /************************************************************ void mpp_domain_init() initialization routine. get the processor information. memory allocation. ************************************************************/ void mpp_domain_init( ) { pe = mpp_pe(); npes = mpp_npes(); root_pe = mpp_root_pe(); }; /* mpp_domain_init */ /*********************************************************** void mpp_domain_end() release memory. ***********************************************************/ void mpp_domain_end () { /* will add something here if needed */ }; /************************************************************ void mpp_define_layout() define domain layout based on given grid resolution and number of processors ***********************************************************/ void mpp_define_layout(int ni, int nj, int ndivs, int layout[]) { int idiv, jdiv; float fdiv; /*first try to divide ndivs in the domain aspect ratio: if imperfect aspect, reduce idiv till it divides ndivs */ fdiv = sqrt((1.0*ndivs*ni)/nj); idiv = floor(fdiv); if(fdiv-idiv > 0.5) idiv = idiv + 1; idiv = (idiv>1) ? idiv : 1; /*for isz=1 line above can give 0*/ while( ndivs%idiv != 0 ) { idiv = idiv - 1; } /*will terminate at idiv=1 if not before*/ jdiv = ndivs/idiv; layout[0] = idiv; layout[1] = jdiv; }; /*********************************************************** void mpp_define_domain_1d(int size, domain1D *domain ) define 1-D domain decomposition. **********************************************************/ void mpp_define_domain_1d(int npts, int ndivs, domain1D *domain ) { int n, npts_left, pos, size; domain->beglist = (int *)malloc(ndivs*sizeof(int)); domain->endlist = (int *)malloc(ndivs*sizeof(int)); if(ndivs > npts ) { mpp_error("mpp_define_domain1d: more divisions requested than rows available. " ); } npts_left = npts; pos = 0; for(n=0; nbeglist[n] = pos; size = ceil((1.0*npts_left)/(ndivs-n)); domain->endlist[n] = pos + size - 1; npts_left=npts_left - size; pos += size; } if(npes == ndivs) { domain->start = domain->beglist[pe]; domain->end = domain->endlist[pe]; domain->size = domain->end - domain->start + 1; domain->sizeg = npts; } }; /* mpp_define_domain_1d */ /************************************************************ void define_domain(int ni, int nj, int layout[], int xhalo, int yhalo, domain2D *domain ) define 2D domain decomposition ************************************************************/ void mpp_define_domain2d(int ni, int nj, int layout[], int xhalo, int yhalo, domain2D *domain ) { domain1D domx, domy; int i, j, posx, posy, n; domain->isclist = (int *)malloc(layout[0]*layout[1]*sizeof(int)); domain->ieclist = (int *)malloc(layout[0]*layout[1]*sizeof(int)); domain->jsclist = (int *)malloc(layout[0]*layout[1]*sizeof(int)); domain->jeclist = (int *)malloc(layout[0]*layout[1]*sizeof(int)); mpp_define_domain_1d(ni, layout[0], &domx); mpp_define_domain_1d(nj, layout[1], &domy); n = 0; for(j=0; jisclist[n] = domx.beglist[i]+xhalo; domain->ieclist[n] = domx.endlist[i]+xhalo; domain->jsclist[n] = domy.beglist[j]+yhalo; domain->jeclist[n] = domy.endlist[j]+yhalo; n++; } } domain->xhalo = xhalo; domain->yhalo = yhalo; domain->isc = domain->isclist[pe]; domain->iec = domain->ieclist[pe]; domain->jsc = domain->jsclist[pe]; domain->jec = domain->jeclist[pe]; domain->isd = domain->isc - xhalo; domain->ied = domain->iec + xhalo; domain->jsd = domain->jsc - yhalo; domain->jed = domain->jec + yhalo; domain->nxc = domain->iec - domain->isc + 1; domain->nyc = domain->jec - domain->jsc + 1; domain->nxd = domain->ied - domain->isd + 1; domain->nyd = domain->jed - domain->jsd + 1; domain->nxg = ni; domain->nyg = nj; mpp_delete_domain1d(&domx); mpp_delete_domain1d(&domy); }; /* mpp_define_domain2d */ /**************************************************************************** void mpp_delete_domain1d(domain1D *domain); release the memory assigned to 1-D domain *****************************************************************************/ void mpp_delete_domain1d(domain1D *domain) { free(domain->beglist); free(domain->endlist); }; /* mpp_delete_domain1d */ /**************************************************************************** void mpp_delete_domain2d(domain2D *domain); release the memory assigned to 2-D domain *****************************************************************************/ void mpp_delete_domain2d(domain2D *domain) { free(domain->isclist); free(domain->ieclist); free(domain->jsclist); free(domain->jeclist); }; /* mpp_delete_domain2d */ /*********************************************************** void get_get_compute_domain(omain2D domain, int *is, int *ie, int *js, int *je) get the compute domain decomposition ***********************************************************/ void mpp_get_compute_domain2d(domain2D domain, int *is, int *ie, int *js, int *je) { *is = domain.isc; *ie = domain.iec; *js = domain.jsc; *je = domain.jec; }; /* mpp_get_compute_domain */ /*********************************************************** void get_get_compute_domain( int *is, int *ie, int *js, int *je) get the compute domain decomposition of current pe list. ***********************************************************/ void mpp_get_compute_domains2d(domain2D domain, int *is, int *ie, int *js, int *je) { int n; for(n=0; n0) mpp_send_int(ldata, lsize, p); } } n = 0; /* receive from other pe and fill the gdata */ for(p = 0; p0) { rbuffer = ( int *) malloc(rsize[p]*sizeof(int)); mpp_recv_int(rbuffer, rsize[p], p ); for(i=0; i0) mpp_send_double(ldata, lsize, p); } } n = 0; /* receive from other pe and fill the gdata */ for(p = 0; p0) { rbuffer = (double *) malloc(rsize[p]*sizeof(double)); mpp_recv_double(rbuffer, rsize[p], p ); for(i=0; i