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