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