00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "PetscTools.hpp"
00030 #include "Exception.hpp"
00031 #include "Warnings.hpp"
00032 #include <iostream>
00033 #include <sstream>
00034 #include <cassert>
00035 #include <cstring>
00036
00037 bool PetscTools::mPetscIsInitialised = false;
00038 unsigned PetscTools::mNumProcessors = 0;
00039 unsigned PetscTools::mRank = 0;
00040 bool PetscTools::mIsolateProcesses = false;
00041
00042
00043 #ifdef DEBUG_BARRIERS
00044 unsigned PetscTools::mNumBarriers = 0u;
00045 #endif
00046
00047 void PetscTools::ResetCache()
00048 {
00049 PetscTruth is_there;
00050 PetscInitialized(&is_there);
00051 if (is_there)
00052 {
00053 mPetscIsInitialised = true;
00054
00055 PetscInt num_procs;
00056 MPI_Comm_size(PETSC_COMM_WORLD, &num_procs);
00057 mNumProcessors = (unsigned) num_procs;
00058
00059 PetscInt my_rank;
00060 MPI_Comm_rank(PETSC_COMM_WORLD, &my_rank);
00061 mRank = (unsigned) my_rank;
00062 }
00063 else
00064 {
00065
00066 mPetscIsInitialised = false;
00067 mNumProcessors = 1;
00068 mRank = 0;
00069 }
00070 }
00071
00072
00073
00074 bool PetscTools::IsSequential()
00075 {
00076 CheckCache();
00077 return (mNumProcessors == 1);
00078 }
00079
00080 bool PetscTools::IsParallel()
00081 {
00082 CheckCache();
00083 return (mNumProcessors > 1);
00084 }
00085
00086 unsigned PetscTools::GetNumProcs()
00087 {
00088 CheckCache();
00089 return mNumProcessors;
00090 }
00091
00092 unsigned PetscTools::GetMyRank()
00093 {
00094 CheckCache();
00095 return mRank;
00096 }
00097
00098 bool PetscTools::AmMaster()
00099 {
00100 CheckCache();
00101 return (mRank == MASTER_RANK || mIsolateProcesses);
00102 }
00103
00104 bool PetscTools::AmTopMost()
00105 {
00106 CheckCache();
00107 return (mRank == mNumProcessors - 1);
00108 }
00109
00110
00111
00112 void PetscTools::Barrier(const std::string callerId)
00113 {
00114 CheckCache();
00115 if (mPetscIsInitialised && !mIsolateProcesses)
00116 {
00117 #ifdef DEBUG_BARRIERS
00118 std::cout << "DEBUG: proc " << PetscTools::GetMyRank() << ": Pre " << callerId << " Barrier " << mNumBarriers << "." << std::endl << std::flush;
00119 #endif
00120 PetscBarrier(PETSC_NULL);
00121 #ifdef DEBUG_BARRIERS
00122 std::cout << "DEBUG: proc " << PetscTools::GetMyRank() << ": Post " << callerId << " Barrier " << mNumBarriers++ << "." << std::endl << std::flush;
00123 #endif
00124 }
00125 }
00126
00127 void PetscTools::BeginRoundRobin()
00128 {
00129 Barrier("PetscTools::RoundRobin");
00130 const unsigned my_rank = GetMyRank();
00131 for (unsigned turn=0; turn<my_rank; turn++)
00132 {
00133 Barrier("PetscTools::RoundRobin");
00134 }
00135 }
00136
00137 void PetscTools::EndRoundRobin()
00138 {
00139 const unsigned num_procs = GetNumProcs();
00140 for (unsigned turn=GetMyRank(); turn<num_procs; turn++)
00141 {
00142 Barrier("PetscTools::RoundRobin");
00143 }
00144 }
00145
00146 void PetscTools::IsolateProcesses(bool isolate)
00147 {
00148 mIsolateProcesses = isolate;
00149 }
00150
00151 bool PetscTools::ReplicateBool(bool flag)
00152 {
00153 CheckCache();
00154 unsigned my_flag = (unsigned) flag;
00155 unsigned anyones_flag_is_true = my_flag;
00156 if (mPetscIsInitialised && !mIsolateProcesses)
00157 {
00158 MPI_Allreduce(&my_flag, &anyones_flag_is_true, 1, MPI_UNSIGNED, MPI_MAX, PETSC_COMM_WORLD);
00159 }
00160 return (anyones_flag_is_true == 1);
00161 }
00162
00163 void PetscTools::ReplicateException(bool flag)
00164 {
00165 bool anyones_error=ReplicateBool(flag);
00166 if (flag)
00167 {
00168
00169 return;
00170 }
00171 if (anyones_error)
00172 {
00173 EXCEPTION("Another process threw an exception; bailing out.");
00174 }
00175 }
00176
00177
00178
00179 Vec PetscTools::CreateVec(int size, int localSize, bool ignoreOffProcEntries)
00180 {
00181 assert(size >= 0);
00182 Vec ret;
00183 VecCreate(PETSC_COMM_WORLD, &ret);
00184 VecSetSizes(ret, localSize, size);
00185 VecSetFromOptions(ret);
00186
00187 if (ignoreOffProcEntries)
00188 {
00189 #if (PETSC_VERSION_MAJOR == 3)
00190 VecSetOption(ret, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
00191 #else
00192 VecSetOption(ret, VEC_IGNORE_OFF_PROC_ENTRIES);
00193 #endif
00194 }
00195
00196 return ret;
00197 }
00198
00199 Vec PetscTools::CreateVec(std::vector<double> data)
00200 {
00201 assert(data.size() > 0);
00202 Vec ret = CreateVec(data.size());
00203
00204 double* p_ret;
00205 VecGetArray(ret, &p_ret);
00206 int lo, hi;
00207 VecGetOwnershipRange(ret, &lo, &hi);
00208
00209 for (int global_index=lo; global_index<hi; global_index++)
00210 {
00211 int local_index = global_index - lo;
00212 p_ret[local_index] = data[global_index];
00213 }
00214 VecRestoreArray(ret, &p_ret);
00215
00216 return ret;
00217 }
00218
00219 Vec PetscTools::CreateAndSetVec(int size, double value)
00220 {
00221 assert(size > 0);
00222 Vec ret = CreateVec(size);
00223
00224 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00225 VecSet(&value, ret);
00226 #else
00227 VecSet(ret, value);
00228 #endif
00229
00230 return ret;
00231 }
00232
00233 void PetscTools::SetupMat(Mat& rMat, int numRows, int numColumns,
00234 unsigned rowPreallocation,
00235 int numLocalRows,
00236 int numLocalColumns,
00237 bool ignoreOffProcEntries)
00238 {
00239 assert(numRows > 0);
00240 assert(numColumns > 0);
00241 if ((int) rowPreallocation>numColumns)
00242 {
00243 WARNING("Preallocation failure: requested number of nonzeros per row greater than number of columns");
00244 rowPreallocation = numColumns;
00245 }
00246
00247 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00248 MatCreate(PETSC_COMM_WORLD,numLocalRows,numLocalColumns,numRows,numColumns,&rMat);
00249 #else //New API
00250 MatCreate(PETSC_COMM_WORLD,&rMat);
00251 MatSetSizes(rMat,numLocalRows,numLocalColumns,numRows,numColumns);
00252 #endif
00253
00254 if (PetscTools::IsSequential())
00255 {
00256 MatSetType(rMat, MATSEQAIJ);
00257 if (rowPreallocation > 0)
00258 {
00259 MatSeqAIJSetPreallocation(rMat, rowPreallocation, PETSC_NULL);
00260 }
00261 }
00262 else
00263 {
00264 MatSetType(rMat, MATMPIAIJ);
00265 if (rowPreallocation > 0)
00266 {
00268 MatMPIAIJSetPreallocation(rMat, rowPreallocation, PETSC_NULL, (PetscInt) (rowPreallocation*0.7), PETSC_NULL);
00269 }
00270 }
00271
00272 MatSetFromOptions(rMat);
00273
00274 if (ignoreOffProcEntries)
00275 {
00276 if (rowPreallocation == 0)
00277 {
00278
00279 WARNING("Ignoring MAT_IGNORE_OFF_PROC_ENTRIES flag because we might set non-zeroes later");
00280 }
00281 else
00282 {
00283 #if (PETSC_VERSION_MAJOR == 3)
00284 MatSetOption(rMat, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
00285 #else
00286 MatSetOption(rMat, MAT_IGNORE_OFF_PROC_ENTRIES);
00287 #endif
00288 }
00289 }
00290 }
00291
00292 void PetscTools::DumpPetscObject(const Mat& rMat, const std::string& rOutputFileFullPath)
00293 {
00294 PetscViewer view;
00295 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00296 PetscViewerFileType type = PETSC_FILE_CREATE;
00297 #else
00298 PetscFileMode type = FILE_MODE_WRITE;
00299 #endif
00300
00301 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(), type, &view);
00302 MatView(rMat, view);
00303 PetscViewerDestroy(view);
00304 }
00305
00306 void PetscTools::DumpPetscObject(const Vec& rVec, const std::string& rOutputFileFullPath)
00307 {
00308 PetscViewer view;
00309 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00310 PetscViewerFileType type = PETSC_FILE_CREATE;
00311 #else
00312 PetscFileMode type = FILE_MODE_WRITE;
00313 #endif
00314
00315 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(), type, &view);
00316 VecView(rVec, view);
00317 PetscViewerDestroy(view);
00318 }
00319
00320 void PetscTools::ReadPetscObject(Mat& rMat, const std::string& rOutputFileFullPath, Vec rParallelLayout)
00321 {
00322
00323
00324
00325
00326
00327
00328
00329 PetscViewer view;
00330 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00331 PetscViewerFileType type = PETSC_FILE_RDONLY;
00332 #else
00333 PetscFileMode type = FILE_MODE_READ;
00334 #endif
00335
00336 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00337 type, &view);
00338 MatLoad(view, MATMPIAIJ, &rMat);
00339 PetscViewerDestroy(view);
00340
00341 if (rParallelLayout != NULL)
00342 {
00343
00344
00345
00346
00347 PetscInt num_rows, num_local_rows;
00348
00349 VecGetSize(rParallelLayout, &num_rows);
00350 VecGetLocalSize(rParallelLayout, &num_local_rows);
00351
00352 Mat temp_mat;
00354 PetscTools::SetupMat(temp_mat, num_rows, num_rows, 100, num_local_rows, num_local_rows, false);
00355
00356 MatCopy(rMat, temp_mat, DIFFERENT_NONZERO_PATTERN);
00357
00358 MatDestroy(rMat);
00359 rMat = temp_mat;
00360 }
00361 }
00362
00363 void PetscTools::ReadPetscObject(Vec& rVec, const std::string& rOutputFileFullPath, Vec rParallelLayout)
00364 {
00365 PetscViewer view;
00366 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00367 PetscViewerFileType type = PETSC_FILE_RDONLY;
00368 #else
00369 PetscFileMode type = FILE_MODE_READ;
00370 #endif
00371
00372 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00373 type, &view);
00374 if (rParallelLayout == NULL)
00375 {
00376 VecLoad(view, VECMPI, &rVec);
00377 }
00378 else
00379 {
00380 VecDuplicate(rParallelLayout, &rVec);
00381 VecLoadIntoVector(view, rVec);
00382 }
00383 PetscViewerDestroy(view);
00384 }