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 #ifndef SPECIAL_SERIAL
00138
00139 bool PetscTools::ReplicateBool(bool flag)
00140 {
00141 unsigned my_flag = (unsigned) flag;
00142 unsigned anyones_flag_is_true;
00143 MPI_Allreduce(&my_flag, &anyones_flag_is_true, 1, MPI_UNSIGNED, MPI_MAX, PETSC_COMM_WORLD);
00144 return (anyones_flag_is_true == 1);
00145 }
00146
00147 void PetscTools::ReplicateException(bool flag)
00148 {
00149 bool anyones_error=ReplicateBool(flag);
00150 if (flag)
00151 {
00152
00153 return;
00154 }
00155 if (anyones_error)
00156 {
00157 EXCEPTION("Another process threw an exception; bailing out.");
00158 }
00159 }
00160
00161
00162
00163
00164
00165 Vec PetscTools::CreateVec(int size, int localSize, bool ignoreOffProcEntries)
00166 {
00167 assert(size>=0);
00168 Vec ret;
00169 VecCreate(PETSC_COMM_WORLD, &ret);
00170 VecSetSizes(ret, localSize, size);
00171 VecSetFromOptions(ret);
00172
00173 if (ignoreOffProcEntries)
00174 {
00175 #if (PETSC_VERSION_MAJOR == 3)
00176 VecSetOption(ret, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
00177 #else
00178 VecSetOption(ret, VEC_IGNORE_OFF_PROC_ENTRIES);
00179 #endif
00180 }
00181
00182 return ret;
00183 }
00184
00185 Vec PetscTools::CreateVec(std::vector<double> data)
00186 {
00187 assert(data.size() > 0);
00188 Vec ret = CreateVec(data.size());
00189
00190 double* p_ret;
00191 VecGetArray(ret, &p_ret);
00192 int lo, hi;
00193 VecGetOwnershipRange(ret, &lo, &hi);
00194
00195 for (int global_index=lo; global_index<hi; global_index++)
00196 {
00197 int local_index = global_index - lo;
00198 p_ret[local_index] = data[global_index];
00199 }
00200 VecRestoreArray(ret, &p_ret);
00201
00202 return ret;
00203 }
00204
00205 Vec PetscTools::CreateAndSetVec(int size, double value)
00206 {
00207 assert(size>0);
00208 Vec ret = CreateVec(size);
00209
00210 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00211 VecSet(&value, ret);
00212 #else
00213 VecSet(ret, value);
00214 #endif
00215
00216 return ret;
00217 }
00218
00219 void PetscTools::SetupMat(Mat& rMat, int numRows, int numColumns,
00220 unsigned rowPreallocation,
00221 int numLocalRows,
00222 int numLocalColumns,
00223 bool ignoreOffProcEntries)
00224 {
00225 assert(numRows>0);
00226 assert(numColumns>0);
00227 if((int) rowPreallocation>numColumns)
00228 {
00229 WARNING("Preallocation failure: requested number of nonzeros per row greater than number of columns");
00230 rowPreallocation=numColumns;
00231 }
00232
00233 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00234 MatCreate(PETSC_COMM_WORLD,numLocalRows,numLocalColumns,numRows,numColumns,&rMat);
00235 #else //New API
00236 MatCreate(PETSC_COMM_WORLD,&rMat);
00237 MatSetSizes(rMat,numLocalRows,numLocalColumns,numRows,numColumns);
00238 #endif
00239
00240
00241 if(PetscTools::IsSequential())
00242 {
00243 MatSetType(rMat, MATSEQAIJ);
00244 if(rowPreallocation>0)
00245 {
00246 MatSeqAIJSetPreallocation(rMat, rowPreallocation, PETSC_NULL);
00247 }
00248 }
00249 else
00250 {
00251 MatSetType(rMat, MATMPIAIJ);
00252 if(rowPreallocation>0)
00253 {
00255 MatMPIAIJSetPreallocation(rMat, rowPreallocation, PETSC_NULL, (PetscInt) (rowPreallocation*0.7), PETSC_NULL);
00256 }
00257 }
00258
00259 MatSetFromOptions(rMat);
00260
00261
00262
00263 if (ignoreOffProcEntries)
00264 {
00265 if (rowPreallocation == 0)
00266 {
00267
00268 WARNING("Ignoring MAT_IGNORE_OFF_PROC_ENTRIES flag because we might set non-zeroes later");
00269 }
00270 else
00271 {
00272 #if (PETSC_VERSION_MAJOR == 3)
00273 MatSetOption(rMat, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
00274 #else
00275 MatSetOption(rMat, MAT_IGNORE_OFF_PROC_ENTRIES);
00276 #endif
00277 }
00278 }
00279 }
00280
00281
00282 void PetscTools::DumpPetscObject(const Mat& rMat, const std::string& rOutputFileFullPath)
00283 {
00284 PetscViewer view;
00285 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00286 PetscViewerFileType type = PETSC_FILE_CREATE;
00287 #else
00288 PetscFileMode type = FILE_MODE_WRITE;
00289 #endif
00290
00291 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00292 type, &view);
00293 MatView(rMat, view);
00294 PetscViewerDestroy(view);
00295 }
00296
00297 void PetscTools::DumpPetscObject(const Vec& rVec, const std::string& rOutputFileFullPath)
00298 {
00299 PetscViewer view;
00300 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00301 PetscViewerFileType type = PETSC_FILE_CREATE;
00302 #else
00303 PetscFileMode type = FILE_MODE_WRITE;
00304 #endif
00305
00306 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00307 type, &view);
00308 VecView(rVec, view);
00309 PetscViewerDestroy(view);
00310 }
00311
00312 void PetscTools::ReadPetscObject(Mat& rMat, const std::string& rOutputFileFullPath, Vec rParallelLayout)
00313 {
00314
00315
00316
00317
00318
00319
00320
00321 PetscViewer view;
00322 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00323 PetscViewerFileType type = PETSC_FILE_RDONLY;
00324 #else
00325 PetscFileMode type = FILE_MODE_READ;
00326 #endif
00327
00328 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00329 type, &view);
00330 MatLoad(view, MATMPIAIJ, &rMat);
00331 PetscViewerDestroy(view);
00332
00333 if (rParallelLayout != NULL)
00334 {
00335
00336
00337
00338
00339 PetscInt num_rows, num_local_rows;
00340
00341 VecGetSize(rParallelLayout, &num_rows);
00342 VecGetLocalSize(rParallelLayout, &num_local_rows);
00343
00344 Mat temp_mat;
00346 PetscTools::SetupMat(temp_mat, num_rows, num_rows, 100, num_local_rows, num_local_rows, false);
00347
00348 MatCopy(rMat, temp_mat, DIFFERENT_NONZERO_PATTERN);
00349
00350 MatDestroy(rMat);
00351 rMat = temp_mat;
00352
00353 }
00354 }
00355
00356 void PetscTools::ReadPetscObject(Vec& rVec, const std::string& rOutputFileFullPath, Vec rParallelLayout)
00357 {
00358 PetscViewer view;
00359 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00360 PetscViewerFileType type = PETSC_FILE_RDONLY;
00361 #else
00362 PetscFileMode type = FILE_MODE_READ;
00363 #endif
00364
00365 PetscViewerBinaryOpen(PETSC_COMM_WORLD, rOutputFileFullPath.c_str(),
00366 type, &view);
00367 if (rParallelLayout == NULL)
00368 {
00369 VecLoad(view, VECMPI, &rVec);
00370 }
00371 else
00372 {
00373 VecDuplicate(rParallelLayout, &rVec);
00374 VecLoadIntoVector(view, rVec);
00375 }
00376 PetscViewerDestroy(view);
00377 }
00378 #endif //SPECIAL_SERIAL (ifndef)
00379
00380 #define COVERAGE_IGNORE //Termination NEVER EVER happens under normal testing conditions.
00381 void PetscTools::Terminate(const std::string& rMessage, const std::string& rFilename, unsigned lineNumber)
00382 {
00383 std::stringstream error_message;
00384
00385 error_message<<"\nChaste termination: " << rFilename << ":" << lineNumber << ": " << rMessage<<"\n";
00386 std::cerr<<error_message.str();
00387
00388
00389
00390 PetscTruth is_there;
00391 PetscInitialized(&is_there);
00392 if (is_there)
00393 {
00394 MPI_Abort(PETSC_COMM_WORLD, EXIT_FAILURE);
00395 }
00396 else
00397 {
00398 exit(EXIT_FAILURE);
00399 }
00400 }
00401 #undef COVERAGE_IGNORE //Termination NEVER EVER happens under normal testing conditions.