escript  Revision_
Distribution.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: distribution                                                     */
00021 
00022 /****************************************************************************/
00023 
00024 /*   Author: Lutz Gross, l.gross@uq.edu.au */
00025 
00026 /****************************************************************************/
00027 
00028 #ifndef __PASO_DISTRIBUTION_H__
00029 #define __PASO_DISTRIBUTION_H__
00030 
00031 #include "Paso.h"
00032 #include "PasoUtil.h"
00033 
00034 namespace paso {
00035 
00036 struct Distribution;
00037 typedef boost::shared_ptr<Distribution> Distribution_ptr;
00038 typedef boost::shared_ptr<const Distribution> const_Distribution_ptr;
00039 
00041 PASO_DLL_API
00042 struct Distribution
00043 {
00044     Distribution(Esys_MPIInfo* mpiInfo, const index_t* firstComponent,
00045                  index_t m, index_t b)
00046     {
00047         mpi_info = Esys_MPIInfo_getReference(mpiInfo);
00048         first_component = new index_t[mpi_info->size+1];
00049         for (dim_t i=0; i < mpi_info->size+1; ++i)
00050             first_component[i] = m*firstComponent[i]+b;
00051     }
00052 
00053     ~Distribution()
00054     {
00055         Esys_MPIInfo_free(mpi_info);
00056         delete[] first_component;
00057     }
00058 
00059     inline index_t getFirstComponent() const
00060     {
00061         return first_component[mpi_info->rank];
00062     }
00063 
00064     inline index_t getLastComponent() const
00065     {
00066         return first_component[mpi_info->rank+1];
00067     }
00068 
00069     inline dim_t getGlobalNumComponents() const
00070     {
00071         return getMaxGlobalComponents()-getMinGlobalComponents();
00072     }
00073 
00074     inline dim_t getMyNumComponents() const
00075     {
00076         return getLastComponent()-getFirstComponent();
00077     }
00078 
00079     inline dim_t getMinGlobalComponents() const
00080     {
00081         return first_component[0];
00082     }
00083 
00084     inline dim_t getMaxGlobalComponents() const
00085     {
00086         return first_component[mpi_info->size];
00087     }
00088 
00089     inline dim_t numPositives(const double* x, dim_t block) const
00090     {
00091         const dim_t my_n = block * getMyNumComponents();
00092         dim_t my_out = util::numPositives(my_n, x);
00093         dim_t out;
00094 
00095 #ifdef ESYS_MPI
00096 #pragma omp single
00097         {
00098             MPI_Allreduce(&my_out, &out, 1, MPI_INT, MPI_SUM, mpi_info->comm);
00099         }
00100 #else
00101         out = my_out;
00102 #endif
00103         return out;
00104     }
00105 
00106     inline double* createRandomVector(dim_t block) const
00107     {
00108         const index_t n_0 = getFirstComponent() * block;
00109         const index_t n_1 = getLastComponent() * block;
00110         const index_t n = getGlobalNumComponents() * block;
00111         const dim_t my_n = n_1-n_0;
00112 
00113         double* out = new double[my_n];
00114 
00115 #pragma omp parallel for schedule(static)
00116         for (index_t i=0; i<my_n; ++i) {
00117             out[i]=fmod(random_seed*(n_0+i+1), 1.);
00118         }
00119 
00120         random_seed = fmod(random_seed * (n+1.7), 1.);
00121         return out;
00122     }
00123 
00124     // process i has nodes with global indices first_component[i] to
00125     // first_component[i+1].
00126     index_t* first_component;
00127     dim_t reference_counter;
00128     Esys_MPIInfo *mpi_info;
00129     static double random_seed;
00130 };
00131 
00132 } // namespace paso
00133 
00134 #endif // __PASO_DISTRIBUTION_H__
00135