escript  Revision_
Coupler.h
Go to the documentation of this file.
00001 
00002 /*****************************************************************************
00003 *
00004 * Copyright (c) 2003-2014 by University of Queensland
00005 * http://www.uq.edu.au
00006 *
00007 * Primary Business: Queensland, Australia
00008 * Licensed under the Open Software License version 3.0
00009 * http://www.opensource.org/licenses/osl-3.0.php
00010 *
00011 * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
00012 * Development 2012-2013 by School of Earth Sciences
00013 * Development from 2014 by Centre for Geoscience Computing (GeoComp)
00014 *
00015 *****************************************************************************/
00016 
00017 
00018 /****************************************************************************/
00019 
00020 /*   Paso: coupler                                            */
00021 
00022 /****************************************************************************/
00023 
00024 /*   Author: Lutz Gross, l.gross@uq.edu.au */
00025 
00026 /****************************************************************************/
00027 
00028 #ifndef __PASO_COUPLER_H__
00029 #define __PASO_COUPLER_H__
00030 
00031 #include "SharedComponents.h"
00032 
00033 namespace paso {
00034 
00035 struct Connector;
00036 typedef boost::shared_ptr<Connector> Connector_ptr;
00037 typedef boost::shared_ptr<const Connector> const_Connector_ptr;
00038 
00039 struct Coupler;
00040 typedef boost::shared_ptr<Coupler> Coupler_ptr;
00041 typedef boost::shared_ptr<const Coupler> const_Coupler_ptr;
00042 
00043 PASO_DLL_API
00044 struct Connector
00045 {
00046     SharedComponents_ptr send;
00047     SharedComponents_ptr recv;
00048     Esys_MPIInfo* mpi_info;
00049 
00050     Connector(SharedComponents_ptr s, SharedComponents_ptr r)
00051     {
00052         Esys_resetError();
00053         if (s->mpi_info != r->mpi_info) {
00054             Esys_setError(SYSTEM_ERROR,
00055                     "Connector: send and recv MPI communicators don't match.");
00056         } else if (s->local_length != r->local_length) {
00057             Esys_setError(SYSTEM_ERROR,
00058                     "Connector: local length of send and recv SharedComponents must match.");
00059         }
00060         send = s;
00061         recv = r;
00062         mpi_info = Esys_MPIInfo_getReference(s->mpi_info);
00063     }
00064 
00066     ~Connector() { Esys_MPIInfo_free(mpi_info); }
00067 
00069     inline Connector_ptr copy() const { return unroll(1); }
00070 
00071     inline Connector_ptr unroll(index_t block_size) const
00072     {
00073         SharedComponents_ptr new_send_shcomp, new_recv_shcomp;
00074         Connector_ptr out;
00075         if (block_size > 1) {
00076             new_send_shcomp.reset(new SharedComponents(send->local_length,
00077                         send->numNeighbors, send->neighbor,
00078                         send->shared, send->offsetInShared,
00079                         block_size, 0, mpi_info));
00080 
00081             new_recv_shcomp.reset(new SharedComponents(recv->local_length,
00082                     recv->numNeighbors, recv->neighbor,
00083                     recv->shared, recv->offsetInShared,
00084                     block_size, 0, mpi_info));
00085         } else {
00086             new_send_shcomp = send;
00087             new_recv_shcomp = recv;
00088         }
00089         if (Esys_noError())
00090             out.reset(new Connector(new_send_shcomp, new_recv_shcomp));
00091         return out;
00092     }
00093 
00094     //inline debug() const
00095     //{
00096     //    for (int i=0; i<recv->numNeighbors; ++i)
00097     //        printf("Coupler: %d receive %d data at %d from %d\n",
00098     //            s->mpi_info->rank,recv->offsetInShared[i+1]-recv->offsetInShared[i],
00099     //            recv->offsetInShared[i],recv->neighbor[i]);
00100     //    for (int i=0; i<send->numNeighbors; ++i)
00101     //        printf("Coupler: %d send %d data at %d to %d\n",
00102     //            s->mpi_info->rank,send->offsetInShared[i+1]-send->offsetInShared[i],
00103     //            send->offsetInShared[i],send->neighbor[i]);
00104     //}
00105 };
00106 
00107 
00108 PASO_DLL_API
00109 struct Coupler
00110 {
00111     Coupler(Connector_ptr, dim_t blockSize);
00112     ~Coupler();
00113 
00114     void startCollect(const double* in);
00115     double* finishCollect();
00116     void copyAll(Coupler_ptr target) const;
00117     void fillOverlap(dim_t n, double* x);
00118     void max(dim_t n, double* x);
00119 
00120     inline const double* borrowLocalData() const { return data; }
00121 
00122     inline const double* borrowRemoteData() const { return recv_buffer; }
00123 
00124     inline dim_t getNumSharedComponents() const
00125     {
00126         return connector->send->numSharedComponents;
00127     }
00128 
00129     inline dim_t getNumOverlapComponents() const
00130     {
00131         return connector->recv->numSharedComponents;
00132     }
00133 
00134     inline dim_t getNumSharedValues() const
00135     {
00136         return getNumSharedComponents() * block_size;
00137     }
00138 
00139     inline dim_t getNumOverlapValues() const
00140     {
00141         return getNumOverlapComponents() * block_size;
00142     }
00143 
00144     inline dim_t getLocalLength() const
00145     {
00146         return connector->send->local_length;
00147     }
00148 
00149     Connector_ptr connector;
00150     dim_t block_size;
00151     bool in_use;
00152 
00153     // unmanaged pointer to data to be sent
00154     double* data;
00155     double* send_buffer;
00156     double* recv_buffer;
00157     MPI_Request* mpi_requests;
00158     MPI_Status* mpi_stati;
00159     Esys_MPIInfo* mpi_info;
00160 };
00161 
00162 
00163 } // namespace paso
00164 
00165 #endif // __PASO_COUPLER_H__
00166