Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

SPMDI.H

Go to the documentation of this file.
00001 /*   _______              __
00002     / ___/ /  ___  __ _  / /  ___
00003    / /__/ _ \/ _ \/  V \/ _ \/ _ \
00004    \___/_//_/\___/_/_/_/_.__/\___/
00005 */
00006 // CHOMBO Copyright (c) 2000-2004, The Regents of the University of
00007 // California, through Lawrence Berkeley National Laboratory (subject to
00008 // receipt of any required approvals from U.S. Dept. of Energy).  All
00009 // rights reserved.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are met:
00013 //
00014 // (1) Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 // (2) Redistributions in binary form must reproduce the above copyright
00017 // notice, this list of conditions and the following disclaimer in the
00018 // documentation and/or other materials provided with the distribution.
00019 // (3) Neither the name of Lawrence Berkeley National Laboratory, U.S.
00020 // Dept. of Energy nor the names of its contributors may be used to endorse
00021 // or promote products derived from this software without specific prior
00022 // written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00028 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00029 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00030 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00031 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00032 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00033 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035 //
00036 // You are under no obligation whatsoever to provide any bug fixes,
00037 // patches, or upgrades to the features, functionality or performance of
00038 // the source code ("Enhancements") to anyone; however, if you choose to
00039 // make your Enhancements available either publicly, or directly to
00040 // Lawrence Berkeley National Laboratory, without imposing a separate
00041 // written license agreement for such Enhancements, then you hereby grant
00042 // the following license: a non-exclusive, royalty-free perpetual license
00043 // to install, use, modify, prepare derivative works, incorporate into
00044 // other computer software, distribute, and sublicense such Enhancements or
00045 // derivative works thereof, in binary and source code form.
00046 //
00047 // TRADEMARKS. Product and company names mentioned herein may be the
00048 // trademarks of their respective owners.  Any rights not expressly granted
00049 // herein are reserved.
00050 //
00051 
00052 #ifndef _SPMDI_H_
00053 #define _SPMDI_H_
00054 
00055 // default implementations for linearization routines.
00056 
00057 template <class T>
00058 int linearSize(const T& inputT)
00059 {
00060   return inputT.linearSize();
00061 }
00062 
00063 template <class T>
00064 void linearIn(T& a_outputT, const void* const inBuf)
00065 {
00066   a_outputT.linearIn(inBuf);
00067 }
00068 
00069 template <class T>
00070 void linearOut(void* const a_outBuf, const T& inputT)
00071 {
00072   inputT.linearOut(a_outBuf);
00073 }
00074 
00075 #ifdef CH_MPI
00076 
00077 /*****************************/
00078 //gather a_input into a a_outVec
00079 /*****************************/
00080 template <class T>
00081 inline void
00082 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00083 {
00084  CH_assert (a_dest >= 0);
00085  CH_assert(a_dest <  numProc());
00086   //now THIS size lives on THIS processor
00087   int isize = linearSize(a_input);
00088 
00089   //make stuff for linearout
00090   void* loclBuf = malloc(isize);
00091   if(loclBuf == NULL)
00092     MayDay::Error("out of memory in gather 1");
00093 
00094   //put linearized T into its proper buffer
00095   linearOut(loclBuf, a_input);
00096 
00097   int nProcess = numProc();
00098   int sendCount = 1;
00099   int recdCount = 1;
00100 
00101   //need to gather isizes onto processor a_dest
00102   int* vectSize = NULL;
00103   int* vectDisp = NULL;
00104   void* sendBuf = static_cast<void*>(&isize);
00105   //allocate received buffer
00106   if(procID() == a_dest)
00107     {
00108       vectSize = new int[nProcess];
00109       vectDisp = new int[nProcess];
00110     }
00111 
00112   int result1 = MPI_Gather(sendBuf, sendCount, MPI_INT,
00113                            vectSize,recdCount, MPI_INT,
00114                            a_dest,  Chombo_MPI::comm);
00115 
00116   if(result1 != MPI_SUCCESS)
00117     MayDay::Error("Gather<T> failed in MPI_Gather 1");
00118 
00119   //make memory for gather, linearin
00120   void* recdBuf = NULL;
00121   if(procID() == a_dest)
00122     {
00123       int itotsize=0;
00124       for(int iproc = 0; iproc < nProcess; iproc++)
00125         {
00126           vectDisp[iproc] = itotsize;
00127           itotsize += vectSize[iproc];
00128         }
00129       recdBuf = malloc(itotsize);
00130       if(recdBuf == NULL)
00131         MayDay::Error("out of memory in gather 2");
00132     }
00133 
00134   //gather data
00135   int result2 = MPI_Gatherv(loclBuf, isize, MPI_BYTE,
00136                             recdBuf, vectSize, vectDisp, MPI_BYTE,
00137                             a_dest, Chombo_MPI::comm);
00138   if(result2 != MPI_SUCCESS)
00139     MayDay::Error("Gather<T> failed in MPI_Gather 2");
00140 
00141   if(procID() == a_dest)
00142     {
00143       //calculate offset into array for current processor
00144       int ioffset = 0;
00145       a_outVec.resize(nProcess);
00146       //need to cast to char* to do pointer arithmetic
00147       char* arithPtr = (char*)recdBuf;
00148       for(int iproc = 0; iproc < nProcess; iproc++)
00149         {
00150           ioffset = vectDisp[iproc];
00151           char* thisProcBuf = arithPtr + ioffset;
00152           linearIn(a_outVec[iproc], thisProcBuf);
00153         }
00154 
00155       //delete memory for dest-specific arrays
00156       delete[] vectSize;
00157       delete[] vectDisp;
00158       free(recdBuf);
00159     }
00160 
00161   //delete memory for local buffer
00162   free(loclBuf);
00163 }
00164 
00165 /*****************************/
00166 //broadcast T everywhere
00167 /*****************************/
00168 template <class T>
00169 inline void
00170 broadcast(T& a_inAndOut,  int a_src)
00171 {
00172  CH_assert (a_src >= 0);
00173  CH_assert(a_src <  numProc());
00174   int isize;
00175   if(procID() == a_src)
00176     isize = linearSize(a_inAndOut);
00177 
00178   MPI_Bcast(&isize, 1, MPI_INT, a_src, Chombo_MPI::comm);
00179 
00180   void* broadBuf = malloc(isize);
00181 
00182   if(broadBuf == NULL)
00183     MayDay::Error("out of memory in broadcast");
00184 
00185   //take inAndOut from src and put it into broadBuf
00186   if(procID() == a_src)
00187       linearOut(broadBuf, a_inAndOut);
00188 
00189   //broadcast broadBuf to all procs
00190   MPI_Bcast(broadBuf, isize, MPI_BYTE, a_src, Chombo_MPI::comm);
00191 
00192   //take broadBuf and put back into inAndOut if not src
00193   if(procID() != a_src)
00194       linearIn(a_inAndOut, broadBuf);
00195 
00196   //delete memory for buffer
00197   free(broadBuf);
00198 }
00199 
00200 /*****************************/
00201 // simple Barrier
00202 /*****************************/
00203 inline void
00204 barrier(void)
00205 {
00206   MPI_Barrier(Chombo_MPI::comm);
00207 }
00208 
00209 #else
00210 /*****************************/
00211 //non-mpi version
00212 /*****************************/
00213 template <class T>
00214 inline void
00215 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00216 {
00217   a_outVec.resize(1);
00218   a_outVec[0] = a_input;
00219 }
00220 /*****************************/
00221 //non-mpi version
00222 /*****************************/
00223 template <class T>
00224 inline void
00225 broadcast(T& a_inAndOut,  int a_src)
00226 {
00227   //nothing to do.  in and out are the same with one proc
00228 }
00229 /*****************************/
00230 //non-mpi version
00231 /*****************************/
00232 inline void
00233 barrier(void)
00234 {
00235   // do nothing in serial
00236 }
00237 
00238 #endif //the mpi thing
00239 
00240 //*************************************
00241 //These should work independent of MPI
00242 //*************************************
00243 
00244 //Vector<T> specialization of linearIn
00245 template <class T>
00246 void
00247 linearListIn(Vector<T>& a_outputT, const void* const a_inBuf)
00248 {
00249   //first entry is the size of the vector
00250   const int* const intBuf = (int*)a_inBuf;
00251   int vecsize = intBuf[0];
00252   Vector<int> vecOffset(vecsize);
00253   //next vecsize entries are offsets of data into buffer
00254   for(int ivec = 0; ivec < vecsize; ivec++)
00255     {
00256       vecOffset[ivec] = intBuf[ivec+1];
00257     }
00258   //next vecsize entries are the actual data
00259   //yes I could do this in one loop but that would
00260   // either
00261   // a) make it less symmetric with linearOut
00262   // and/or
00263   // b) make both of them far less readable
00264   a_outputT.resize(vecsize);
00265   const char* const charbuf = (char*)a_inBuf;
00266   for(int ivec = 0; ivec < vecsize; ivec++)
00267     {
00268       const char* const dataLoc = charbuf + vecOffset[ivec];
00269       linearIn(a_outputT[ivec], dataLoc);
00270     }
00271 }
00272 
00273 //Vector<T> specialization of linearOut
00274 template <class T>
00275 void
00276 linearListOut(void* const a_outBuf, const Vector<T>& a_input)
00277 {
00278   //first entry is the size of the vector
00279   int* const intBuf = (int*)a_outBuf;
00280   intBuf[0] = a_input.size();
00281   int vecsize = intBuf[0];
00282   Vector<int> vecOffset(vecsize);
00283   //next vecsize entries are offsets of data into buffer
00284   //next vecsize entries are the actual data
00285   int ioffset = (vecsize+1)*sizeof(int);
00286   for(int ivec = 0; ivec < vecsize; ivec++)
00287     {
00288       intBuf[ivec+1] = ioffset;
00289       vecOffset[ivec] = ioffset;
00290       ioffset += linearSize(a_input[ivec]);
00291     }
00292   //yes I could do this in one loop but that would
00293   // either
00294   // a) make it less symmetric with linearIn
00295   // and/or
00296   // b) make both of them far less readable
00297   char* const charBuf = (char*)a_outBuf;
00298   for(int ivec = 0; ivec < vecsize; ivec++)
00299     {
00300       char* const dataLoc = charBuf + vecOffset[ivec];
00301       linearOut(dataLoc, a_input[ivec]);
00302     }
00303 }
00304 
00305 //Vector<T> specialization of linearSize
00306 template <class T>
00307 int
00308 linearListSize(const Vector<T>& a_input)
00309 {
00310   //first entry is the size of the vector (int)
00311   //next vecsize entries are offsets of data into buffer (int)
00312   //next vecsize entries are the actual data
00313   int itotsize = (a_input.size() + 1)*sizeof(int);
00314   for(int ivec = 0; ivec < a_input.size(); ivec++)
00315     {
00316       itotsize += linearSize(a_input[ivec]);
00317     }
00318   return itotsize;
00319 }
00320 
00321 #endif

Generated on Wed Oct 5 13:52:09 2005 for Chombo&AMRSelfGravity by  doxygen 1.4.1