escript
Revision_
|
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