diff --git a/src/baseconfiguration.cpp b/src/baseconfiguration.cpp index c8ab726..d57aa9b 100644 --- a/src/baseconfiguration.cpp +++ b/src/baseconfiguration.cpp @@ -25,28 +25,25 @@ const std::string ConfigurationBase::k_extension_token = "%ext%"; const std::string ConfigurationBase::k_outer_token = "%s%"; const std::string ConfigurationBase::k_inner_token = "%i%"; -const config_map ConfigurationBase::default_config = {{"verbose", "false"}, - {"registered", "registered.xdmf"}, {"map", "map.xdmf"}, {"lambda", "auto"}, {"mask", ""}, - {"registered_h5_path", "/registered"}, {"map_h5_path", "/map"}, {"lambda_mult", "1.0"}, - {"with_memory", "true"}, {"save_intermediate_frames", "false"}, +const config_map ConfigurationBase::arg_options = {{"fixed", ""}, {"moved", ""}, + {"nodespacing", ""}, {"registered", "registered.xdmf"}, {"map", "map.xdmf"}, + {"lambda", "auto"}, {"mask", ""}, {"registered_h5_path", "/registered"}, + {"map_h5_path", "/map"}, {"lambda_mult", "1.0"}, {"intermediate_template", "%name%-intermediate-%s%-%i%%ext%"}, {"intermediate_map_template", "%name%-intermediate-map-%s%-%i%%ext%"}, {"intermediate_directory", "intermediates"}, {"max_iterations", "100"}}; +const config_map ConfigurationBase::bool_options = { + {"verbose", "false"}, {"with_memory", "true"}, {"save_intermediate_frames", "false"}}; + const std::vector ConfigurationBase::required_options = { "fixed", "moved", "nodespacing"}; -const std::vector ConfigurationBase::arg_options = {"fixed", "moved", "mask", - "nodespacing", "registered", "map", "lambda", "lambda_mult", "intermediate_template", - "intermediate_directory", "max_iterations", "registered_h5_path", "map_h5_path"}; - -const std::vector ConfigurationBase::bool_options = { - "verbose", "with_memory", "save_intermediate_frames"}; - ConfigurationBase::ConfigurationBase(const int &argc, char const *const *argv) - : config(default_config), arguments(argv + 1, argv + argc), - invocation_name(get_invocation_name(argv[0])) + : arguments(argv + 1, argv + argc), invocation_name(get_invocation_name(argv[0])) { + config.insert(arg_options.cbegin(), arg_options.cend()); + config.insert(bool_options.cbegin(), bool_options.cend()); } void ConfigurationBase::validate_config() @@ -54,12 +51,12 @@ void ConfigurationBase::validate_config() std::list missing; for (auto &req_it : ConfigurationBase::required_options) { - if (config.find(req_it) == config.cend()) + if (config.find(req_it) == config.cend() || config[req_it].empty()) { missing.push_back(req_it); } } - if (missing.size() > 0) + if (!missing.empty()) { std::ostringstream errmsg; errmsg << "Missing required argument(s) \""; diff --git a/src/baseconfiguration.hpp b/src/baseconfiguration.hpp index 3e836ff..d77a1bd 100644 --- a/src/baseconfiguration.hpp +++ b/src/baseconfiguration.hpp @@ -30,6 +30,7 @@ namespace bf = boost::filesystem; #include "types.hpp" +#include "exceptions.hpp" using config_map = std::map; @@ -39,29 +40,57 @@ class ConfigurationBase { template typename std::enable_if::value, T>::type grab(const std::string key) const { - T val; - std::istringstream(config.at(key)) >> std::boolalpha >> val; - return val; + try + { + T val; + std::istringstream(config.at(key)) >> std::boolalpha >> val; + return val; + } + catch (std::out_of_range &err) + { + throw InternalError("Attempt to access non-existent configuration option", __FILE__, __LINE__); + } } template typename std::enable_if::value && !std::is_same::value, T>::type grab(const std::string key) const { - return static_cast(std::stoll(config.at(key))); + try + { + return static_cast(std::stoll(config.at(key))); + } + catch (std::out_of_range &err) + { + throw InternalError("Attempt to access non-existent configuration option", __FILE__, __LINE__); + } } template typename std::enable_if::value && !std::is_same::value, T>::type grab(const std::string key) const { - return static_cast(std::stold(config.at(key))); - } + try + { + return static_cast(std::stold(config.at(key))); + } + catch (std::out_of_range &err) + { + throw InternalError("Attempt to access non-existent configuration option", __FILE__, __LINE__); + } +} template typename std::enable_if::value, T>::type grab(std::string key) const { - return config.at(key); + try + { + return config.at(key); + } + catch (std::out_of_range &err) + { + throw InternalError("Attempt to access non-existent configuration option", __FILE__, __LINE__); + } } static std::string get_invocation_name(const std::string& argzero); @@ -80,10 +109,9 @@ class ConfigurationBase { std::vector arguments; std::string invocation_name; - static const config_map default_config; static const std::vector required_options; - static const std::vector arg_options; - static const std::vector bool_options; + static const config_map arg_options; + static const config_map bool_options; }; #endif // CONFIGURATION_HPP diff --git a/src/baseloader.cpp b/src/baseloader.cpp index a65d01a..0123dd1 100644 --- a/src/baseloader.cpp +++ b/src/baseloader.cpp @@ -33,7 +33,7 @@ bool BaseLoader::register_loader(const std::string &name, loader_creator loader) } std::ostringstream err; err << "Loader named " << name << " already registered."; - throw std::runtime_error(err.str()); + throw InternalError(err.str(), __FILE__, __LINE__); } BaseLoader_unique BaseLoader::find_loader(const std::string &path, MPI_Comm comm) @@ -53,5 +53,5 @@ BaseLoader_unique BaseLoader::find_loader(const std::string &path, MPI_Comm comm } std::ostringstream err; err << "Failed to find suitable loader for \"" << path << "\"."; - throw std::runtime_error(err.str()); + throw InvalidLoaderError(err.str()); } diff --git a/src/basewriter.cpp b/src/basewriter.cpp index a4b68fc..14d84aa 100644 --- a/src/basewriter.cpp +++ b/src/basewriter.cpp @@ -54,7 +54,7 @@ std::string BaseWriter::find_writer_for_filename(const std::string &filename) } std::ostringstream err; err << "No suitable writer available for extension \"" << extension << "\"."; - throw std::runtime_error(err.str()); + throw BadConfigurationError(err.str()); } BaseWriter_unique BaseWriter::get_writer_by_name( @@ -68,7 +68,7 @@ BaseWriter_unique BaseWriter::get_writer_by_name( } std::ostringstream err; err << "No registered writer named \"" << name << "\"."; - throw std::runtime_error(err.str()); + throw BadConfigurationError(err.str()); } BaseWriter_unique BaseWriter::get_writer_for_filename(const std::string &filename, MPI_Comm comm) @@ -78,12 +78,12 @@ BaseWriter_unique BaseWriter::get_writer_for_filename(const std::string &filenam return BaseWriter::get_writer_by_name( BaseWriter::find_writer_for_filename(filename), filename, comm); } - catch (const std::runtime_error &errstr) + catch (const pFIREExpectedError &errstr) { std::ostringstream err; err << "No suitable writer available for file \"" << filename << "\"." << "\n(" << errstr.what() << ")\n"; - throw std::runtime_error(err.str()); + throw BadConfigurationError(err.str()); } } diff --git a/src/basewriter.hpp b/src/basewriter.hpp index d97e9cd..b0e0e52 100644 --- a/src/basewriter.hpp +++ b/src/basewriter.hpp @@ -25,6 +25,7 @@ #include #include "types.hpp" +#include "exceptions.hpp" class BaseWriter { public: @@ -107,7 +108,7 @@ BaseWriter::register_writer() } std::ostringstream err; err << "Writer named " << WriterClass::writer_name << " already registered."; - throw std::runtime_error(err.str()); + throw InternalError(err.str(), __FILE__, __LINE__); } #endif // BASEWRITER_HPP diff --git a/src/basis.cpp b/src/basis.cpp index a4d6374..eb7a17f 100644 --- a/src/basis.cpp +++ b/src/basis.cpp @@ -18,6 +18,7 @@ #include #include "debug.hpp" +#include "exceptions.hpp" #include "petsc_debug.hpp" #include "indexing.hpp" #include "iterator_routines.hpp" @@ -125,7 +126,7 @@ Mat_unique build_basis_matrix( PetscErrorCode perr = MatCreateMPIAIJWithArrays( comm, idxn.size() - 1, PETSC_DECIDE, m_size, n_size, idxn.data(), idxm.data(), mdat.data(), m_basis.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); #ifdef DEBUG_VERBOSE matrix_dbg_print(comm, *m_basis, "Basis Matrix"); @@ -142,12 +143,12 @@ Mat_unique build_warp_matrix( integer mat_size = std::accumulate(img_shape.begin(), img_shape.end(), 1, std::multiplies<>()); if (img_shape.size() < ndim) { - throw std::runtime_error("image dimensions must match ndim"); + throw InternalError("image dimensions must match ndim", __FILE__, __LINE__); } if (displacements.size() < ndim) { - throw std::runtime_error("must have displacement vector for each image dimension"); + throw InternalError("must have displacement vector for each image dimension", __FILE__, __LINE__); } intvector img_shape_trunc(ndim, 0); @@ -173,7 +174,7 @@ Mat_unique build_warp_matrix( // lambda needed here anyway to capture comm auto get_raw_array = [comm](floating*& a, const Vec* v) -> void { PetscErrorCode p = VecGetArray(*v, &a); - CHKERRABORT(comm, p); + CHKERRXX(p); }; n_ary_for_each(get_raw_array, raw_arrs.begin(), raw_arrs.end(), displacements.begin()); @@ -236,7 +237,7 @@ Mat_unique build_warp_matrix( // lambda needed here anyway to capture comm auto restore_raw_array = [comm](floating*& a, const Vec* v) -> void { PetscErrorCode p = VecRestoreArray(*v, &a); - CHKERRABORT(comm, p); + CHKERRXX(p); }; n_ary_for_each(restore_raw_array, raw_arrs.begin(), raw_arrs.end(), displacements.begin()); @@ -244,7 +245,7 @@ Mat_unique build_warp_matrix( perr = MatCreateMPIAIJWithArrays( comm, idxn.size() - 1, idxn.size() - 1, mat_size, mat_size, idxn.data(), idxm.data(), mdat.data(), warp.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); debug_creation(*warp, "Warp matrix"); return warp; diff --git a/src/dcmloader.cpp b/src/dcmloader.cpp index 8b026ab..1d3a85c 100644 --- a/src/dcmloader.cpp +++ b/src/dcmloader.cpp @@ -58,19 +58,19 @@ DCMLoader::DCMLoader(const std::string &path, MPI_Comm comm) status = dataset->findAndGetLongInt(DcmTagKey(TG_IMG, TE_ROWS), tmp); if (status.bad()) { - throw std::runtime_error("Failed to read image shape data"); + throw InvalidLoaderError("Failed to read image shape data"); } this->_shape[0] = tmp; status = dataset->findAndGetLongInt(DcmTagKey(TG_IMG, TE_COLS), tmp); if (status.bad()) { - throw std::runtime_error("Failed to read image shape data"); + throw InvalidLoaderError("Failed to read image shape data"); } this->_shape[1] = tmp; status = dataset->findAndGetLongInt(DcmTagKey(TG_IMG, TE_FRAMES), tmp); if (status.bad()) { - throw std::runtime_error("Failed to read image shape data"); + throw InvalidLoaderError("Failed to read image shape data"); } this->_shape[2] = tmp; } @@ -123,7 +123,7 @@ void DCMLoader::copy_scaled_chunk( } default: { - throw std::runtime_error("Unhandled image bit depth."); + throw InvalidLoaderError("Unhandled image bit depth."); break; } } diff --git a/src/elastic.cpp b/src/elastic.cpp index 51344fd..b8f3311 100644 --- a/src/elastic.cpp +++ b/src/elastic.cpp @@ -129,7 +129,7 @@ void Elastic::innerloop(integer outer_count) innerstep(inum, recalculate_lambda); recalculate_lambda = false; - if (configuration.grab("save_intermediate_frames")) + if (configuration.grab("save_intermediate_flames")) { save_debug_frame(outer_count, inum); save_debug_map(outer_count, inum); @@ -138,9 +138,9 @@ void Elastic::innerloop(integer outer_count) // check convergence and break if below threshold floating posmax, negmax; PetscErrorCode perr = VecMax(*m_workspace->m_delta, nullptr, &posmax); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecMin(*m_workspace->m_delta, nullptr, &negmax); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); floating amax = std::max(std::fabs(posmax), std::fabs(negmax)); PetscPrintf(m_comm, "Maximum displacement: %.2f\n", amax); floating aavg; @@ -149,7 +149,7 @@ void Elastic::innerloop(integer outer_count) PetscPrintf(m_comm, "Average displacement: %.2f\n", aavg); floating curr_mi = m_p_registered->mutual_information(m_fixed); PetscPrintf(m_comm, "Mutual information: %f\n", curr_mi); - if (aavg < m_convergence_thres || curr_mi <= prev_mi) + if (aavg < m_convergence_thres)// || curr_mi <= prev_mi) { PetscPrintf(m_comm, "Generation %i converged after %i iterations.\n\n", outer_count, inum); break; @@ -169,7 +169,7 @@ void Elastic::innerstep(integer inum, bool recalculate_lambda) // TODO: can we reuse here? PetscErrorCode perr = MatTransposeMatMult(*m_workspace->m_tmat, *m_workspace->m_tmat, MAT_INITIAL_MATRIX, PETSC_DEFAULT, normmat.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*normmat, std::string("Mat_normal") + std::to_string(inum)); // precondition tmat2 block_precondition(*normmat, m_p_map->size(), m_p_map->m_ndim); @@ -189,15 +189,15 @@ void Elastic::innerstep(integer inum, bool recalculate_lambda) floating total_mult = lapl_mult * lambda_mult * m_lambda; // calculate tmat2 + lambda*lapl2 perr = MatAXPY(*normmat, total_mult, *m_p_map->laplacian(), DIFFERENT_NONZERO_PATTERN); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // calculate rvec, to do this need to reuse stacked vector for [f-m f-m f-m f-m] perr = VecWAXPY( *m_workspace->m_globaltmps[0], -1.0, *m_p_registered->global_vec(), *m_fixed.global_vec()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); m_workspace->duplicate_single_grad_to_stacked(0); perr = MatMultTranspose(*m_workspace->m_tmat, *m_workspace->m_stacktmp, *m_workspace->m_rhs); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // apply memory term if needed if (configuration.grab("with_memory")) @@ -205,15 +205,15 @@ void Elastic::innerstep(integer inum, bool recalculate_lambda) // build -lambda*a Vec_unique disp = create_unique_vec(); perr = VecDuplicate(m_p_map->displacements(), disp.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecCopy(m_p_map->displacements(), *disp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScale(*disp, -total_mult); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // calculate vecdot(lapl_2, -lambda*a) and add to rhs in one operation perr = MatMultAdd(*m_p_map->laplacian(), *disp, *m_workspace->m_rhs, *m_workspace->m_rhs); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } // Force free tmat as no longer needed @@ -222,17 +222,17 @@ void Elastic::innerstep(integer inum, bool recalculate_lambda) // solve for delta a KSP_unique m_ksp = create_unique_ksp(); perr = KSPCreate(m_comm, m_ksp.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = KSPSetOperators(*m_ksp, *normmat, *normmat); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = KSPSetUp(*m_ksp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = KSPSetFromOptions(*m_ksp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = KSPSetUp(*m_ksp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = KSPSolve(*m_ksp, *m_workspace->m_rhs, *m_workspace->m_delta); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // update map m_p_map->update(*m_workspace->m_delta); // warp image @@ -260,19 +260,19 @@ void Elastic::calculate_tmat(integer iternum __attribute__((unused))) // Calculate average intensity 0.5(f+m) // Constant offset needed later, does not affect gradients PetscErrorCode perr = VecSet(*m_workspace->m_globaltmps[m_fixed.ndim()], -1.0); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // NB Z = aX + bY + cZ has call signature VecAXPBYPCZ(Z, a, b, c, X, Y) because reasons.... perr = VecAXPBYPCZ(*m_workspace->m_globaltmps[m_fixed.ndim()], 0.5, 0.5, 1, *m_fixed.global_vec(), *m_p_registered->global_vec()); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // scatter this to local for later perr = DMGlobalToLocalBegin(*m_fixed.dmda(), *m_workspace->m_globaltmps[m_fixed.ndim()], INSERT_VALUES, *m_workspace->m_localtmp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = DMGlobalToLocalEnd(*m_fixed.dmda(), *m_workspace->m_globaltmps[m_fixed.ndim()], INSERT_VALUES, *m_workspace->m_localtmp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // find average gradients for (uinteger idim = 0; idim < m_fixed.ndim(); idim++) @@ -284,7 +284,7 @@ void Elastic::calculate_tmat(integer iternum __attribute__((unused))) // Negate average intensity to get 1 - 0.5(f+m) as needed by algorithm perr = VecScale(*m_workspace->m_globaltmps[m_fixed.ndim()], -1.0); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // scatter grads into stacked vector m_workspace->scatter_grads_to_stacked(); @@ -292,12 +292,12 @@ void Elastic::calculate_tmat(integer iternum __attribute__((unused))) // 3. copy basis into p_tmat m_workspace->m_tmat = create_unique_mat(); perr = MatDuplicate(*m_p_map->basis(), MAT_COPY_VALUES, m_workspace->m_tmat.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*m_workspace->m_tmat, std::string("Mat_tmat_") + std::to_string(iternum)); // 4. left diagonal multiply p_tmat with stacked vector perr = MatDiagonalScale(*m_workspace->m_tmat, *m_workspace->m_stacktmp, nullptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } void Elastic::save_debug_map(integer outer_count, integer inner_count) @@ -326,8 +326,9 @@ void Elastic::save_debug_map(integer outer_count, integer inner_count) if (!bf::exists(intermediates_path)) { std::ostringstream errss; - errss << "Intermediate frame output path " << intermediates_path << " does not exist."; - throw std::runtime_error(errss.str()); + errss << "Intermediate frame output path " << intermediates_path << " does not exist, but " + << "should have already been created."; + throw InternalError(errss.str(), __FILE__, __LINE__); } output_path = intermediates_path; } @@ -437,19 +438,19 @@ floating Elastic::approximate_optimum_lambda(Mat& mat_a, Mat& mat_b, floating la if (recalc_first) { perr = MatAXPY(*mat_c, lambda_mult * x_lo, mat_b, DIFFERENT_NONZERO_PATTERN); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); y_lo = get_condnum_by_poweriter(*mat_c, 0.01, 100); } recalc_first = true; // Calculate at initial guess perr = MatAXPY(*mat_c, lambda_mult * (x_mid - x_lo), mat_b, DIFFERENT_NONZERO_PATTERN); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); y_mid = get_condnum_by_poweriter(*mat_c, 0.01, 100); // calculate at higher value perr = MatAXPY(*mat_c, lambda_mult * (x_hi - x_mid), mat_b, DIFFERENT_NONZERO_PATTERN); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); y_hi = get_condnum_by_poweriter(*mat_c, 0.01, 100); PetscPrintf( diff --git a/src/exceptions.cpp b/src/exceptions.cpp index a91c28d..2813687 100644 --- a/src/exceptions.cpp +++ b/src/exceptions.cpp @@ -15,11 +15,14 @@ #include "exceptions.hpp" +#include #include +#include #include #include "gitstate.hpp" +#include "versioning.hpp" constexpr std::string_view abort_info_pre = R"FATAL(!!! FATAL ERROR !!!: @@ -32,19 +35,38 @@ Help is available through the pFIRE issue tracker on github, but first please en 2. Your input files are not corrupt 3. If you are running on HPC please check there are no hardware issues -If you have checked the above and the bug still happens: https://github.com/INSIGNEO/pFIRE/issues +If you have checked the above and the bug still occurs please report it via +https://github.com/INSIGNEO/pFIRE/issues Your report should include: - Input configuration file -- Details of the images being registered -- The exact pFIRE version: )FATAL"; +- Details of the images being registered (format, dimensions) +- Basic hardware details, operating system and version +- The exact pFIRE version: -constexpr std::string_view abort_info_post = R"FATAL( + - )FATAL"; + +constexpr std::string_view abort_info_libheader = R"FATAL( +- The library versions in use: )FATAL"; +constexpr std::string_view abort_info_petsc = " - Petsc Version: "; +constexpr std::string_view abort_info_boost = " - Boost Version: "; + +#ifdef USE_OIIO +constexpr std::string_view abort_info_oiio = " - OpenImageIO Version: "; +#endif + +#ifdef USE_DCMTK +constexpr std::string_view abort_info_dcmtk = " - DCMTK Version: "; +#endif //USE_DCMTK + +constexpr std::string_view abort_info_post = R"FATAL( +)FATAL"; + void abort_with_unhandled_error(){ @@ -53,6 +75,10 @@ void abort_with_unhandled_error(){ std::exception_ptr eptr = std::current_exception(); + // Try to separate threads that arrive here together + // to avoid garbling stdout too much + std::this_thread::sleep_for(std::chrono::milliseconds(200*rank)); + try { if (eptr) { @@ -65,11 +91,7 @@ void abort_with_unhandled_error(){ << e.what() << "\n\"\"\"\n"; } - if(rank == 0){ - std::cout << abort_info_pre - << git_version_string() - << abort_info_post; - } + print_abort_message(); MPI_Abort(MPI_COMM_WORLD, -1); @@ -80,9 +102,24 @@ void sigterm_handler(int signal){ int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if(rank == 0){ + std::cout << "Rank " << rank << " received signal " << signal; + + std::this_thread::sleep_for(std::chrono::milliseconds(50*rank)); + print_abort_message(); +} + +void print_abort_message(){ + std::cout << abort_info_pre << git_version_string() + << abort_info_libheader + << abort_info_petsc << get_version_string_petsc() << "\n" + << abort_info_boost << get_version_string_boost() << "\n" +#ifdef USE_OIIO + << abort_info_oiio << get_version_string_oiio() << "\n" +#endif //USE_OIIO +#ifdef USE_DCMTK + << abort_info_dcmtk << get_version_string_dcmtk() << "\n" +#endif //USE_DCMTK << abort_info_post; - } } diff --git a/src/exceptions.hpp b/src/exceptions.hpp index 310bb03..541b792 100644 --- a/src/exceptions.hpp +++ b/src/exceptions.hpp @@ -22,62 +22,85 @@ void abort_with_unhandled_error(); void sigterm_handler(int signal); +void print_abort_message(); -class InvalidLoaderError: public std::runtime_error { +class pFIREBaseError: public std::runtime_error { public: - InvalidLoaderError(const std::string& filepath) : std::runtime_error(build_errstring(filepath)) + pFIREBaseError(const std::string &msg, const std::string &file, size_t line_num) + : std::runtime_error(msg), _where(build_wherestring(file, line_num)) { } + const char *where() { return _where.c_str(); } + protected: - static std::string build_errstring(const std::string& path) + std::string _where; + + static std::string build_wherestring(const std::string &file, size_t line_num) { std::ostringstream errss; - errss << "Failed to read data from " << path << ", wrong loader or file corrupt."; + errss << file << ":" << line_num; return errss.str(); } + + static std::string build_errstring(const std::string &what) + { + std::ostringstream errss; + errss << what; + return errss.str(); + } + }; -class FileNotFoundError: public std::runtime_error { +class pFIREExpectedError: public pFIREBaseError { public: - FileNotFoundError(const std::string& filepath) : std::runtime_error(build_errstring(filepath)) {} + pFIREExpectedError(const std::string &msg, const std::string& file, size_t line_num) + : pFIREBaseError(msg, file, line_num) + {} + +}; + +class InvalidLoaderError: public pFIREExpectedError { +public: + InvalidLoaderError(const std::string &path, std::string file = "unknown", size_t line_num = 0) + : pFIREExpectedError(build_errstring(path), file, line_num) + { + } protected: - static std::string build_errstring(const std::string& path) + static std::string build_errstring(const std::string &path) { std::ostringstream errss; - errss << "Failed to open " << path << ", wrong permissions or file does not exist."; + errss << "Failed to read data from " << path << ", wrong loader or file corrupt."; return errss.str(); } }; -class InternalError: public std::runtime_error { +class FileNotFoundError: public pFIREExpectedError { public: - InternalError(const std::string& what, std::string file = "unknown", integer line = 0) - : std::runtime_error(build_errstring(what, file, line)) + FileNotFoundError(const std::string &path, std::string file = "unknown", size_t line_num = 0) + : pFIREExpectedError(build_errstring(path), file, line_num) { } protected: - static std::string build_errstring( - const std::string& what, std::string file, integer line) + static std::string build_errstring(const std::string &path) { std::ostringstream errss; - errss << "Internal error at " << file << ":" << line << " \"" << what << "\""; + errss << "Failed to open " << path << ", wrong permissions or file does not exist."; return errss.str(); } }; -class BadConfigurationError: public std::runtime_error { +class InternalError: public pFIREBaseError { public: - BadConfigurationError(const std::string& what, std::string file = "unknown", integer line = 0) - : std::runtime_error(build_errstring(what, file, line)) + InternalError(const std::string &what, std::string file = "unknown", size_t line = 0) + : pFIREBaseError(build_errstring(what, file, line), file, line) { } protected: - static std::string build_errstring( - const std::string& what, std::string file, integer line) + std::string build_errstring(const std::string &what, const std::string &file, size_t line) { std::ostringstream errss; errss << "Internal error at " << file << ":" << line << " \"" << what << "\""; @@ -85,4 +108,30 @@ class BadConfigurationError: public std::runtime_error { } }; +class BadConfigurationError: public pFIREExpectedError { +public: + BadConfigurationError(const std::string &msg, std::string file = "unknown", size_t line = 0) + : pFIREExpectedError(build_errstring(msg), file, line) + { + } + +}; + +class InvalidWriterError: public pFIREExpectedError { +public: + InvalidWriterError(const std::string &msg, std::string file = "unknown", size_t line = 0) + : pFIREExpectedError(build_errstring(msg), file, line) + { + } +}; + + +class WriterError: public pFIREExpectedError { +public: + WriterError(const std::string &msg, std::string file = "unknown", size_t line = 0) + : pFIREExpectedError(build_errstring(msg), file, line) + { + } +}; + #endif // EXCEPTIONS_HPP diff --git a/src/fd_routines.cpp b/src/fd_routines.cpp index b50a935..c67f8df 100644 --- a/src/fd_routines.cpp +++ b/src/fd_routines.cpp @@ -15,38 +15,40 @@ #include "fd_routines.hpp" +#include "exceptions.hpp" + Vec_unique fd::gradient_to_global_unique(const DM &dmda, const Vec &localvec, integer dim) { // First sanity check we have a valid local vector for the DMDA // (should have matching global, local and comm size) Vec dm_local_vec; PetscErrorCode perr = DMGetLocalVector(dmda, &dm_local_vec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); if (!vecs_equivalent(dm_local_vec, localvec)) { - throw std::runtime_error("provided vector invalid for given dmda object"); + throw InternalError("provided vector invalid for given dmda object", __FILE__, __LINE__); } perr = DMRestoreLocalVector(dmda, &dm_local_vec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // New global vec must be a dmda global Vec_unique grad = create_unique_vec(); perr = DMCreateGlobalVector(dmda, grad.get()); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // Access local of this to have ghosts, global of grad to avoid later copy // Recall grad and image share a DMDA floating ***img_array, ***grad_array; // acceptable to use raw ptrs here as memory handled by PETSc perr = DMDAVecGetArray(dmda, localvec, &img_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = DMDAVecGetArray(dmda, *(grad.get()), &grad_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); integer i_lo, i_hi, j_lo, j_hi, k_lo, k_hi; // This returns corners + widths so add lo to get hi perr = DMDAGetCorners(dmda, &i_lo, &j_lo, &k_lo, &i_hi, &j_hi, &k_hi); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); i_hi += i_lo; j_hi += j_lo; k_hi += k_lo; @@ -68,9 +70,9 @@ Vec_unique fd::gradient_to_global_unique(const DM &dmda, const Vec &localvec, in } // Release pointers and allow petsc to cleanup perr = DMDAVecRestoreArray(dmda, localvec, &img_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = DMDAVecRestoreArray(dmda, *(grad.get()), &grad_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); return grad; } @@ -81,27 +83,27 @@ void fd::gradient_existing(const DM &dmda, const Vec &srcvec, Vec &tgtvec, integ // (should have matching global, local and comm size) Vec dm_local_vec; PetscErrorCode perr = DMGetLocalVector(dmda, &dm_local_vec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); if (!vecs_equivalent(dm_local_vec, srcvec)) { - throw std::runtime_error("provided srcvec invalid for given dmda object"); + throw InternalError("provided srcvec invalid for given dmda object", __FILE__, __LINE__); } perr = DMRestoreLocalVector(dmda, &dm_local_vec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); // Access local of this to have ghosts, global of grad to avoid later copy // Recall grad and image share a DMDA floating ***img_array, ***grad_array; // acceptable to use raw ptrs here as memory handled by PETSc perr = DMDAVecGetArray(dmda, srcvec, &img_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = DMDAVecGetArray(dmda, tgtvec, &grad_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); integer i_lo, i_hi, j_lo, j_hi, k_lo, k_hi; // This returns corners + widths so add lo to get hi perr = DMDAGetCorners(dmda, &i_lo, &j_lo, &k_lo, &i_hi, &j_hi, &k_hi); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); i_hi += i_lo; j_hi += j_lo; k_hi += k_lo; @@ -123,7 +125,7 @@ void fd::gradient_existing(const DM &dmda, const Vec &srcvec, Vec &tgtvec, integ } // Release pointers and allow petsc to cleanup perr = DMDAVecRestoreArray(dmda, srcvec, &img_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = DMDAVecRestoreArray(dmda, tgtvec, &grad_array); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); } diff --git a/src/hdfwriter.cpp b/src/hdfwriter.cpp index 519e9b8..4c8cf95 100644 --- a/src/hdfwriter.cpp +++ b/src/hdfwriter.cpp @@ -58,10 +58,10 @@ void HDFWriter::write_3d_dataset_parallel(uinteger ndim, const std::vectorshape().begin(), loader->shape().end(), existing->shape().begin(), existing->shape().end(), std::equal_to<>())) { - throw std::runtime_error("New image must have same shape as existing"); + throw InternalError("New image must have same shape as existing", __FILE__, __LINE__); } new_image = Image::duplicate(*existing); } @@ -79,15 +79,15 @@ Image::load_file(const std::string& path, const ImageBase* existing, MPI_Comm co intvector shape(3, 0), offset(3, 0); PetscErrorCode perr = DMDAGetCorners( *new_image->dmda(), &offset[0], &offset[1], &offset[2], &shape[0], &shape[1], &shape[2]); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // std::transform(shape.cbegin(), shape.cend(), offset.cbegin(), shape.begin(), std::minus<>()); floating ***vecptr(nullptr); perr = DMDAVecGetArray(*new_image->dmda(), *new_image->global_vec(), &vecptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); loader->copy_scaled_chunk(vecptr, shape, offset); perr = DMDAVecRestoreArray(*new_image->dmda(), *new_image->global_vec(), &vecptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); new_image->normalize(); diff --git a/src/imagebase.cpp b/src/imagebase.cpp index 87cd334..340013b 100644 --- a/src/imagebase.cpp +++ b/src/imagebase.cpp @@ -28,6 +28,7 @@ #include "iterator_routines.hpp" #include "map.hpp" #include "math_utils.hpp" +#include "exceptions.hpp" #include "baseloader.hpp" @@ -49,7 +50,7 @@ ImageBase::ImageBase(const intvector& shape, MPI_Comm comm) } else { - throw std::runtime_error("image shape should be 2D or 3D"); + throw InternalError("image shape should be 2D or 3D", __FILE__, __LINE__); } } if (m_shape[2] == 1) @@ -65,26 +66,26 @@ const floating* ImageBase::get_raw_data_ro() const { const floating* ptr; PetscErrorCode perr = VecGetArrayRead(*m_globalvec, &ptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return ptr; } void ImageBase::release_raw_data_ro(const floating*& ptr) const { PetscErrorCode perr = VecRestoreArrayRead(*m_globalvec, &ptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } Vec_unique ImageBase::get_raw_data_row_major() const { Vec_unique rmlocalpart = create_unique_vec(); PetscErrorCode perr = VecDuplicate(*m_globalvec, rmlocalpart.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); intvector locs(3, 0); intvector widths(3, 0); perr = DMDAGetCorners(*m_dmda, &locs[0], &locs[1], &locs[2], &widths[0], &widths[1], &widths[2]); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); integer ownedlo; perr = VecGetOwnershipRange(*m_globalvec, &ownedlo, nullptr); @@ -99,18 +100,18 @@ Vec_unique ImageBase::get_raw_data_row_major() const IS_unique src_is = create_unique_is(); perr = ISCreateStride(m_comm, localsize, ownedlo, 1, src_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); IS_unique tgt_is = create_unique_is(); perr = ISCreateGeneral(m_comm, localsize, cmidxn.data(), PETSC_USE_POINTER, tgt_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); VecScatter_unique sct = create_unique_vecscatter(); perr = VecScatterCreate(*m_globalvec, *src_is, *rmlocalpart, *tgt_is, sct.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*sct, *m_globalvec, *rmlocalpart, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*sct, *m_globalvec, *rmlocalpart, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return rmlocalpart; } @@ -118,13 +119,13 @@ Vec_unique ImageBase::get_raw_data_row_major() const floating ImageBase::masked_normalize(const Mask& mask) { Vec_unique tmp = create_unique_vec(); - PetscErrorCode perr = VecDuplicate(*m_globalvec, tmp.get());CHKERRABORT(m_comm, perr); - perr = VecPointwiseMult(*tmp, *mask.global_vec(), *m_globalvec);CHKERRABORT(m_comm, perr); + PetscErrorCode perr = VecDuplicate(*m_globalvec, tmp.get());CHKERRXX(perr); + perr = VecPointwiseMult(*tmp, *mask.global_vec(), *m_globalvec);CHKERRXX(perr); floating norm; - perr = VecSum(*tmp, &norm);CHKERRABORT(m_comm, perr); + perr = VecSum(*tmp, &norm);CHKERRXX(perr); norm = mask.npoints() / norm; - perr = VecScale(*m_globalvec, norm);CHKERRABORT(m_comm, perr); + perr = VecScale(*m_globalvec, norm);CHKERRXX(perr); return norm; } @@ -132,7 +133,7 @@ floating ImageBase::masked_normalize(const Mask& mask) void ImageBase::copy_data(const ImageBase &img) { PetscErrorCode perr = VecCopy(*img.global_vec(), *m_globalvec); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); update_local_from_global(); } @@ -141,7 +142,7 @@ Vec_unique ImageBase::gradient(integer dim) // New global vec must be a duplicate of image global Vec_shared grad = create_shared_vec(); PetscErrorCode perr = VecDuplicate(*(m_globalvec), grad.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Ensure we have up to date ghost cells DMGlobalToLocalBegin(*m_dmda, *m_globalvec, INSERT_VALUES, *m_localvec); @@ -167,10 +168,10 @@ floating ImageBase::normalize() { floating norm; PetscErrorCode perr = VecMax(*m_globalvec, nullptr, &norm); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); norm = 1.0 / norm; perr = VecScale(*m_globalvec, norm); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return norm; } @@ -205,10 +206,10 @@ void ImageBase::initialize_dmda() dof_per_node, stencil_width, // dof per node, stencil size nullptr, nullptr, nullptr, // partition sizes nullptr -> petsc chooses m_dmda.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = DMSetUp(*(m_dmda)); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } void ImageBase::initialize_vectors() @@ -217,19 +218,19 @@ void ImageBase::initialize_vectors() m_localvec = create_shared_vec(); m_globalvec = create_shared_vec(); perr = DMCreateGlobalVector(*m_dmda, m_globalvec.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*m_globalvec, std::string("image_global_") + std::to_string(instance_id)); perr = DMCreateLocalVector(*m_dmda, m_localvec.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*m_localvec, std::string("image_local_") + std::to_string(instance_id)); } void ImageBase::update_local_from_global() { PetscErrorCode perr = DMGlobalToLocalBegin(*m_dmda, *m_globalvec, INSERT_VALUES, *m_localvec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = DMGlobalToLocalEnd(*m_dmda, *m_globalvec, INSERT_VALUES, *m_localvec); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); } Vec_unique ImageBase::get_raw_data_natural() const @@ -258,19 +259,19 @@ floating ImageBase::mutual_information(const ImageBase &other) integer img_localsize; PetscErrorCode perr = VecGetLocalSize(*m_globalvec, &img_localsize); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); floating max1, max2; - perr = VecMax(*m_globalvec, nullptr, &max1);CHKERRABORT(m_comm, perr); - perr = VecMax(*other.global_vec(), nullptr, &max2);CHKERRABORT(m_comm, perr); + perr = VecMax(*m_globalvec, nullptr, &max1);CHKERRXX(perr); + perr = VecMax(*other.global_vec(), nullptr, &max2);CHKERRXX(perr); floating max = std::max(max1, max2); // Only need RO data from PETSc vecs floating const *x_data, *y_data; perr = VecGetArrayRead(*m_globalvec, &x_data); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecGetArrayRead(*other.global_vec(), &y_data); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); for (integer idx = 0; idx < img_localsize; idx++) { diff --git a/src/imagebase.hpp b/src/imagebase.hpp index 401e29a..606b0b4 100644 --- a/src/imagebase.hpp +++ b/src/imagebase.hpp @@ -97,7 +97,7 @@ std::vector ImageBase::mpi_get_chunksize() const intvector sizes(3, 0); PetscErrorCode perr = DMDAGetCorners(*m_dmda, nullptr, nullptr, nullptr, &sizes[0], &sizes[1], &sizes[2]); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); std::vector out(sizes.begin(), sizes.end()); @@ -113,7 +113,7 @@ std::vector ImageBase::mpi_get_offset() const intvector offsets(3, 0); PetscErrorCode perr = DMDAGetCorners(*m_dmda, &offsets[0], &offsets[1], &offsets[2], nullptr, nullptr, nullptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); std::vector out(offsets.begin(), offsets.end()); diff --git a/src/iniconfiguration.cpp b/src/iniconfiguration.cpp index a150aa1..8cc42c7 100644 --- a/src/iniconfiguration.cpp +++ b/src/iniconfiguration.cpp @@ -76,7 +76,7 @@ void IniConfig::parse_arguments() std::exit(0); } - if (vm.count("help") || !vm.count("config-file")) + if (vm.count("help") > 0 || vm.count("config-file") != 1 ) { // TODO improve to iterate over options std::cout << usage() << std::endl << cmdline_visible << std::endl; @@ -112,11 +112,11 @@ void IniConfig::read_config_file(const std::string &config_path) for (const auto &it : config_data) { std::string key = ba::to_lower_copy(it.first); - if (std::find(arg_options.cbegin(), arg_options.cend(), key) != arg_options.cend()) + if (arg_options.find(key) != arg_options.cend()) { config[key] = it.second.data(); } - else if (std::find(bool_options.cbegin(), bool_options.cend(), key) != bool_options.cend()) + else if (bool_options.find(key) != bool_options.cend()) { config[key] = boost::to_lower_copy(it.second.data()); } @@ -126,7 +126,7 @@ void IniConfig::read_config_file(const std::string &config_path) } } - if (unknowns.size() > 0) + if (!unknowns.empty()) { std::ostringstream unkss; std::copy(unknowns.begin(), unknowns.end(), std::ostream_iterator(unkss, ", ")); diff --git a/src/laplacian.cpp b/src/laplacian.cpp index 7700d0c..e88112f 100644 --- a/src/laplacian.cpp +++ b/src/laplacian.cpp @@ -94,6 +94,6 @@ Mat_unique build_laplacian_matrix( comm, idxn.size() - 1, PETSC_DECIDE, matsize, matsize, idxn.data(), idxm.data(), mdat.data(), lapl_mat.get()); debug_creation(*lapl_mat, "laplacian"); - CHKERRABORT(comm, perr); + CHKERRXX(perr); return lapl_mat; } diff --git a/src/map.cpp b/src/map.cpp index d570680..7417256 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -53,7 +53,7 @@ void Map::apply_mask_to_basis() // First stack basis to depth of map Vec_unique stacked_basis = create_unique_vec(); PetscErrorCode perr = MatCreateVecs(*m_basis, nullptr, stacked_basis.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); repeat_stack(*m_mask.global_vec(), *stacked_basis); @@ -64,7 +64,7 @@ void Map::apply_mask_to_basis() // Mask applies directly to image side of basis perr = MatDiagonalScale(*m_basis, *stacked_basis, *map_side); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } Vec_unique Map::calculate_map_mask(Vec& stacked_mask ) @@ -72,16 +72,16 @@ Vec_unique Map::calculate_map_mask(Vec& stacked_mask ) // Create map mask from image mask and basis Vec_unique map_mask = create_unique_vec(); PetscErrorCode perr = MatCreateVecs(*m_basis, map_mask.get(), nullptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = MatMultTranspose(*m_basis, stacked_mask, *map_mask); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Dilate to include surrounding nodes // First need 1 copy in global layout Vec_unique map_mask_global = create_unique_vec(); perr = DMCreateGlobalVector(*map_dmda, map_mask_global.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); copy_nth_from_stack_nat_to_petsc(*map_mask_global, *map_mask, *map_dmda, 0); // Now dilate @@ -97,7 +97,7 @@ Vec_unique Map::calculate_map_mask(Vec& stacked_mask ) void Map::update(const Vec& delta_vec) { PetscErrorCode perr = VecAXPY(*m_displacements, 1, delta_vec); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } std::unique_ptr Map::interpolate(const floatvector& new_spacing) @@ -117,7 +117,7 @@ std::unique_ptr Map::interpolate(const floatvector& new_spacing) m_comm, map_shape, new_map->map_shape, scalings, offsets, m_ndim, m_ndim + 1); PetscErrorCode perr = MatMult(*interp, *m_displacements, *new_map->m_displacements); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return new_map; } @@ -142,10 +142,10 @@ void Map::initialize_dmda() const dof_per_node, stencil_width, // dof per node, stencil size nullptr, nullptr, nullptr, // partition sizes nullptr -> petsc chooses map_dmda.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = DMSetUp(*(map_dmda)); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } void Map::alloc_displacements() { MatCreateVecs(*m_basis, m_displacements.get(), nullptr); } @@ -154,7 +154,7 @@ intvector Map::calculate_map_shape(intvector const& image_shape, floatvector con { if (image_shape.size() != nodespacing.size()) { - throw std::runtime_error("Image and nodespacing dimensions must match"); + throw InternalError("Image and nodespacing dimensions must match", __FILE__, __LINE__); } // want always to have odd number of nodes so find num nodes for each half, @@ -191,7 +191,7 @@ std::unique_ptr Map::warp(const Image& image, WorkSpace& wksp) // interpolate map to image nodes with basis PetscErrorCode perr = MatMult(*m_basis, *m_displacements, *wksp.m_stacktmp); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); wksp.scatter_stacked_to_grads_noreorder(); // build warp matrix @@ -206,27 +206,27 @@ std::unique_ptr Map::warp(const Image& image, WorkSpace& wksp) // first need image in natural ordering Vec_unique src_nat = create_unique_vec(); perr = DMDACreateNaturalVector(*image.dmda(), src_nat.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*src_nat, "Vec_source_natural"); perr = DMDAGlobalToNaturalBegin(*image.dmda(), *image.global_vec(), INSERT_VALUES, *src_nat); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = DMDAGlobalToNaturalEnd(*image.dmda(), *image.global_vec(), INSERT_VALUES, *src_nat); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // do mult Vec_unique tgt_nat = create_unique_vec(); perr = DMDACreateNaturalVector(*image.dmda(), tgt_nat.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*tgt_nat, "Vec_target_natural"); perr = MatMult(*warp, *src_nat, *tgt_nat); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // create new image and insert data in petsc ordering std::unique_ptr new_image = Image::duplicate(image); perr = DMDANaturalToGlobalBegin(*image.dmda(), *tgt_nat, INSERT_VALUES, *new_image->global_vec()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = DMDANaturalToGlobalEnd(*image.dmda(), *tgt_nat, INSERT_VALUES, *new_image->global_vec()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return new_image; } @@ -238,7 +238,7 @@ std::pair Map::get_dmda_local_extents() const intvector widths(3, 0); PetscErrorCode perr = DMDAGetCorners(*map_dmda, &locs[0], &locs[1], &locs[2], &widths[0], &widths[1], &widths[2]); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return std::make_pair(locs, widths); } @@ -253,7 +253,7 @@ Vec_unique Map::get_raw_data_row_major(uinteger dim) const intvector widths(3, 0); PetscErrorCode perr = DMDAGetCorners(*map_dmda, &locs[0], &locs[1], &locs[2], &widths[0], &widths[1], &widths[2]); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); integer startelem, localsize; perr = VecGetOwnershipRange(*tmp_vec, &startelem, &localsize); localsize -= startelem; @@ -261,7 +261,7 @@ Vec_unique Map::get_raw_data_row_major(uinteger dim) const // source is simple stride IS_unique src_is = create_unique_is(); perr = ISCreateStride(m_comm, localsize, startelem, 1, src_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // do rowmaj -> colmaj scatter as in Image intvector cmidxn(localsize); @@ -272,19 +272,19 @@ Vec_unique Map::get_raw_data_row_major(uinteger dim) const }); IS_unique tgt_is = create_unique_is(); perr = ISCreateGeneral(m_comm, localsize, cmidxn.data(), PETSC_USE_POINTER, tgt_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // now do scatter Vec_unique cmaj_vec(create_unique_vec()); perr = VecDuplicate(*tmp_vec, cmaj_vec.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); VecScatter_unique sct(create_unique_vecscatter()); perr = VecScatterCreate(*tmp_vec, *src_is, *cmaj_vec, *tgt_is, sct.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*sct, *tmp_vec, *cmaj_vec, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*sct, *tmp_vec, *cmaj_vec, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return cmaj_vec; } @@ -295,17 +295,17 @@ Vec_unique Map::get_single_dim_petsc(uinteger dim) const initialize_dmda(); if (dim >= m_ndim) { - throw std::runtime_error("Index too large for map dimensions"); + throw InternalError("Index too large for map dimensions", __FILE__, __LINE__); } // Allocate temp vec Vec_unique tmp_data = create_unique_vec(); PetscErrorCode perr = DMCreateGlobalVector(*map_dmda, tmp_data.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); AO ao_petsctonat; // N.B this is not going to be a leak, we are just borrowing a Petsc managed // obj. perr = DMDAGetAO(*map_dmda, &ao_petsctonat); // Destroying this would break the dm - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Target range is owned part of new vec integer startelem, localsize; @@ -313,9 +313,9 @@ Vec_unique Map::get_single_dim_petsc(uinteger dim) const localsize -= startelem; IS_unique tgt_is(create_unique_is()); perr = ISCreateStride(m_comm, localsize, startelem, 1, tgt_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = AOPetscToApplicationIS(ao_petsctonat, *tgt_is); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); <<<<<<< HEAD // Source range is equivalent range offset to dimension @@ -325,16 +325,16 @@ Vec_unique Map::get_single_dim_petsc(uinteger dim) const >>>>>>> develop IS_unique src_is(create_unique_is()); perr = ISCreateStride(m_comm, localsize, startelem + offset, 1, src_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); VecScatter_unique sct = create_unique_vecscatter(); perr = VecScatterCreate(*m_displacements, *src_is, *tmp_data, *tgt_is, sct.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*sct, *m_displacements, *tmp_data, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*sct, *m_displacements, *tmp_data, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return tmp_data; }*/ @@ -344,14 +344,14 @@ Vec_unique Map::get_single_dim_petsc(uinteger dim) const initialize_dmda(); if (dim >= m_ndim) { - throw std::runtime_error("Index too large for map dimensions"); + throw InternalError("Index too large for map dimensions", __FILE__, __LINE__); } // Get dim data Vec_unique nat_data = get_single_dim_natural(dim); // Allocate temp vec Vec_unique tmp_data(create_unique_vec()); PetscErrorCode perr = DMCreateGlobalVector(*map_dmda, tmp_data.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); DMDANaturalToGlobalBegin(*map_dmda, *nat_data, INSERT_VALUES, *tmp_data); DMDANaturalToGlobalEnd(*map_dmda, *nat_data, INSERT_VALUES, *tmp_data); @@ -364,12 +364,12 @@ Vec_unique Map::get_single_dim_natural(uinteger dim) const initialize_dmda(); if (dim >= m_ndim) { - throw std::runtime_error("Index too large for map dimensions"); + throw InternalError("Index too large for map dimensions", __FILE__, __LINE__); } // Allocate temp vec Vec_unique tmp_data = create_unique_vec(); PetscErrorCode perr = DMDACreateNaturalVector(*map_dmda, tmp_data.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Target range is owned part of new vec integer startelem, localsize; @@ -377,7 +377,7 @@ Vec_unique Map::get_single_dim_natural(uinteger dim) const localsize -= startelem; IS_unique tgt_is(create_unique_is()); perr = ISCreateStride(m_comm, localsize, startelem, 1, tgt_is.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Source range is owned part of vec offset by dimension length integer offset = dim * this->size(); @@ -386,12 +386,12 @@ Vec_unique Map::get_single_dim_natural(uinteger dim) const VecScatter_unique sct = create_unique_vecscatter(); perr = VecScatterCreate(*m_displacements, *src_is, *tmp_data, *tgt_is, sct.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*sct, *m_displacements, *tmp_data, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*sct, *m_displacements, *tmp_data, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return tmp_data; } @@ -414,12 +414,12 @@ void Map::calculate_laplacian() { integer startrow, endrow; PetscErrorCode perr = VecGetOwnershipRange(*m_displacements, &startrow, &endrow); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); Mat_unique lapl = build_laplacian_matrix(m_comm, map_shape, startrow, endrow, m_ndim + 1); perr = MatTransposeMatMult(*lapl, *lapl, MAT_INITIAL_MATRIX, PETSC_DEFAULT, m_lapl.get()); debug_creation(*m_lapl, "Mat_l_squared"); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } std::pair Map::get_displacement_ownershiprange() const @@ -427,7 +427,7 @@ std::pair Map::get_displacement_ownershiprange() const std::pair range; PetscErrorCode perr = VecGetOwnershipRange(*m_displacements, &range.first, &range.second); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return range; } @@ -436,14 +436,14 @@ const floating* Map::get_raw_data_ro() const { const floating* ptr; PetscErrorCode perr = VecGetArrayRead(*m_displacements, &ptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return ptr; } void Map::release_raw_data_ro(const floating*& ptr) const { PetscErrorCode perr = VecRestoreArrayRead(*m_displacements, &ptr); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } floatvector Map::low_corner() const diff --git a/src/mask.cpp b/src/mask.cpp index 038aad9..045686f 100644 --- a/src/mask.cpp +++ b/src/mask.cpp @@ -17,6 +17,7 @@ #include "baseloader.hpp" #include "iterator_routines.hpp" +#include "exceptions.hpp" Mask::Mask(const intvector& shape, MPI_Comm comm) : ImageBase(shape, comm) @@ -61,7 +62,7 @@ Mask::load_file(const std::string& path, const ImageBase* existing, MPI_Comm com loader->shape().begin(), loader->shape().end(), existing->shape().begin(), existing->shape().end(), std::equal_to<>())) { - throw std::runtime_error("New mask must have same shape as existing"); + throw InternalError("New mask must have same shape as existing", __FILE__, __LINE__); } new_mask = Mask::duplicate(*existing); } @@ -73,15 +74,15 @@ Mask::load_file(const std::string& path, const ImageBase* existing, MPI_Comm com intvector shape(3, 0), offset(3, 0); PetscErrorCode perr = DMDAGetCorners( *new_mask->dmda(), &offset[0], &offset[1], &offset[2], &shape[0], &shape[1], &shape[2]); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // std::transform(shape.cbegin(), shape.cend(), offset.cbegin(), shape.begin(), std::minus<>()); floating*** vecptr(nullptr); perr = DMDAVecGetArray(*new_mask->dmda(), *new_mask->global_vec(), &vecptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); loader->copy_scaled_chunk(vecptr, shape, offset); perr = DMDAVecRestoreArray(*new_mask->dmda(), *new_mask->global_vec(), &vecptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); new_mask->binarize(); @@ -92,7 +93,7 @@ integer Mask::npoints() const { floating total_points; PetscErrorCode perr = VecSum(*m_globalvec, &total_points); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); return static_cast(total_points); } diff --git a/src/math_utils.hpp b/src/math_utils.hpp index 1bb3053..f10afa4 100644 --- a/src/math_utils.hpp +++ b/src/math_utils.hpp @@ -20,6 +20,8 @@ #include +#include "exceptions.hpp" + void quadratic_from_points(floating x_1, floating x_2, floating x_3, floating y_1, floating y_2, floating y_3, floating &a, floating &b, floating &c); @@ -42,12 +44,12 @@ inline void explain_memory(const intvector &image_size, const intvector &map_siz { if (image_size.size() < 2 || image_size.size() > 3) { - throw std::runtime_error("Image should be 2D or 3D"); + throw InternalError("Image should be 2D or 3D", __FILE__, __LINE__); } if (map_size.size() != image_size.size()) { - throw std::runtime_error("Map and image dimensions should match"); + throw InternalError("Map and image dimensions should match", __FILE__, __LINE__); } integer ndim = image_size.size(); diff --git a/src/oiiowriter.cpp b/src/oiiowriter.cpp index 320b131..c32be42 100644 --- a/src/oiiowriter.cpp +++ b/src/oiiowriter.cpp @@ -18,6 +18,7 @@ #include #include "image.hpp" +#include "exceptions.hpp" const std::string OIIOWriter::writer_name = "OpenImageIO"; const std::vector OIIOWriter::extensions = {".png",".jpg",".jpeg",".tiff"}; @@ -39,18 +40,18 @@ std::string OIIOWriter::write_image(const Image& image) auto img = OIIO::ImageOutput::create(filename); if (img == nullptr) { - throw std::runtime_error("Failed to open image output file"); + throw WriterError("Failed to open image output file"); } OIIO::ImageSpec spec(image.shape()[0], image.shape()[1], 1, OIIO::TypeDesc::UINT16); img->open(filename, spec); floating* pixdata; PetscErrorCode perr = VecGetArray(*imgvec, &pixdata); - CHKERRABORT(_comm, perr); + CHKERRXX(perr); img->write_image(OIIO::TypeDesc::DOUBLE, pixdata); img->close(); perr = VecRestoreArray(*imgvec, &pixdata); - CHKERRABORT(_comm, perr); + CHKERRXX(perr); //Manual ptr management if needed #if OIIO_VERSION < 10903 @@ -63,5 +64,5 @@ std::string OIIOWriter::write_image(const Image& image) std::string OIIOWriter::write_map(const Map& map __attribute__((unused))) { - throw std::runtime_error("Cannot save map using OIIO."); + throw InvalidWriterError("Cannot save map using OIIO."); } diff --git a/src/petsc_helpers.cpp b/src/petsc_helpers.cpp index 04dcab6..bc328d3 100644 --- a/src/petsc_helpers.cpp +++ b/src/petsc_helpers.cpp @@ -19,6 +19,8 @@ #include #include +#include "exceptions.hpp" + floating diagonal_sum(const Mat& matrix) { MPI_Comm comm; @@ -26,10 +28,10 @@ floating diagonal_sum(const Mat& matrix) Vec_unique diag = create_unique_vec(); PetscErrorCode perr = MatCreateVecs(matrix, diag.get(), nullptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = MatGetDiagonal(matrix, *diag); - CHKERRABORT(comm, perr); + CHKERRXX(perr); floating diagsum; perr = VecSum(*diag, &diagsum); @@ -42,9 +44,9 @@ bool vecs_equivalent(const Vec &vec1, const Vec &vec2) // Ensure two vectors have the same local size, global size. and comm. MPI_Comm comm1, comm2; PetscErrorCode perr = PetscObjectGetComm((PetscObject)vec1, &comm1); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = PetscObjectGetComm((PetscObject)vec2, &comm2); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); if (comm1 != comm2) { return false; @@ -52,9 +54,9 @@ bool vecs_equivalent(const Vec &vec1, const Vec &vec2) integer globalsize1, globalsize2; perr = VecGetSize(vec1, &globalsize1); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = VecGetSize(vec2, &globalsize2); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); if (globalsize1 != globalsize2) { return false; @@ -62,9 +64,9 @@ bool vecs_equivalent(const Vec &vec1, const Vec &vec2) integer localsize1, localsize2; perr = VecGetLocalSize(vec1, &localsize1); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); perr = VecGetLocalSize(vec2, &localsize2); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); if (localsize1 != localsize2) { return false; @@ -80,10 +82,10 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) // Normalize luminance block of matrix to spatial blocks using diagonal norm Vec_unique diag = create_unique_vec(); PetscErrorCode perr = MatCreateVecs(normmat, diag.get(), nullptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); debug_creation(*diag, "Vec_block_normalise"); perr = MatGetDiagonal(normmat, *diag); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // index where spatial dims stop and intensity dim starts integer crit_idx = size * ndim; @@ -91,7 +93,7 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) // Find rank-local sums for spatial and luminance blocks integer rowstart, rowend; perr = VecGetOwnershipRange(*diag, &rowstart, &rowend); - CHKERRABORT(comm, perr); + CHKERRXX(perr); integer localsize = rowend - rowstart; floatvector norm(2, 0.0); // norm[0] is spatial, norm[1] is luminance integer spt_end = crit_idx - rowstart; @@ -99,7 +101,7 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) floating* ptr; perr = VecGetArray(*diag, &ptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); for (integer idx = 0; idx < spt_end; idx++) { norm[0] += ptr[idx]; @@ -109,7 +111,7 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) norm[1] += ptr[idx]; } perr = VecRestoreArray(*diag, &ptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // MPI_AllReduce to sum over all processes MPI_Allreduce(MPI_IN_PLACE, norm.data(), 2, MPI_DOUBLE, MPI_SUM, comm); @@ -121,7 +123,7 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) // reuse diag vector to hold scaling values perr = VecGetArray(*diag, &ptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); for (integer idx = 0; idx < spt_end; idx++) { ptr[idx] = 1; @@ -131,10 +133,10 @@ void block_precondition(const Mat& normmat, integer size, integer ndim) ptr[idx] = lum_scale; } perr = VecRestoreArray(*diag, &ptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = MatDiagonalScale(normmat, *diag, nullptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); } floating get_condnum_by_poweriter(const Mat& matrix, floating conv_thres, integer max_iter) @@ -147,9 +149,9 @@ floating get_condnum_by_poweriter(const Mat& matrix, floating conv_thres, intege // Get smallest eigenvalue by spectral shift Mat_unique e_n_mat = create_unique_mat(); PetscErrorCode perr = MatDuplicate(matrix, MAT_DO_NOT_COPY_VALUES, e_n_mat.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = MatShift(*e_n_mat, -eigen_lo); - CHKERRABORT(comm, perr); + CHKERRXX(perr); floating eigen_hi = get_eigenvalue_by_poweriter(*e_n_mat, conv_thres, max_iter) + eigen_lo; @@ -168,7 +170,7 @@ floating get_eigenvalue_by_poweriter(const Mat& matrix, floating conv_thres, int { if (conv_thres <= 0) { - throw std::domain_error("conv_thres must be greater than 0"); + throw InternalError("conv_thres must be greater than 0", __FILE__, __LINE__); } MPI_Comm comm; @@ -177,37 +179,37 @@ floating get_eigenvalue_by_poweriter(const Mat& matrix, floating conv_thres, int // Initial guess at b_0 Vec_unique b = create_unique_vec(); PetscErrorCode perr = MatCreateVecs(matrix, b.get(), nullptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecSet(*b, 1.0); - CHKERRABORT(comm, perr); + CHKERRXX(perr); Vec_unique b_next = create_unique_vec(); perr = MatCreateVecs(matrix, b_next.get(), nullptr); - CHKERRABORT(comm, perr); + CHKERRXX(perr); integer curr_iter = 0; floating delta = 2 * conv_thres; floating lambda = 1.0; floating b_dot; perr = VecDot(*b, *b, &b_dot); - CHKERRABORT(comm, perr); + CHKERRXX(perr); while (delta > conv_thres && curr_iter++ < max_iter) { perr = MatMult(matrix, *b, *b_next); - CHKERRABORT(comm, perr); + CHKERRXX(perr); floating b_bn_dot; perr = VecDot(*b, *b_next, &b_bn_dot); - CHKERRABORT(comm, perr); + CHKERRXX(perr); floating new_lambda = b_bn_dot / b_dot; delta = std::abs(new_lambda - lambda); perr = VecDot(*b_next, *b_next, &b_dot); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScale(*b_next, 1. / std::sqrt(b_dot)); - CHKERRABORT(comm, perr); + CHKERRXX(perr); b.swap(b_next); lambda = new_lambda; @@ -229,7 +231,7 @@ void repeat_stack(const Vec& subvec, const Vec& stacked) PetscObjectGetComm(reinterpret_cast(subvec), &comm); PetscObjectGetComm(reinterpret_cast(stacked), &comm2); if (comm != comm2){ - throw std::runtime_error("stacked and subvec must share a communicator"); + throw InternalError("stacked and subvec must share a communicator", __FILE__, __LINE__); } integer subvec_len; @@ -241,18 +243,18 @@ void repeat_stack(const Vec& subvec, const Vec& stacked) std::ostringstream errss; errss << "stacked length (" << stacked_len << ") not a multiple of subvec length (" << subvec_len << ")."; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } // Get extents of local data in subvector integer startelem, datasize; PetscErrorCode perr = VecGetOwnershipRange(subvec, &startelem, &datasize); - CHKERRABORT(comm, perr); + CHKERRXX(perr); datasize -= startelem; // Create IS for source indices in stacked array IS_unique src_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem, 1, src_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); integer stack_total = stacked_len / subvec_len; integer offset = 0; // Track offset @@ -261,17 +263,17 @@ void repeat_stack(const Vec& subvec, const Vec& stacked) IS_unique tgt_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem + offset, 1, tgt_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Create scatterer and add to array VecScatter_unique scatterer = create_unique_vecscatter(); perr = VecScatterCreate(subvec, *src_is, stacked, *tgt_is, scatterer.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*scatterer, subvec, stacked, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*scatterer, subvec, stacked, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(comm, perr); + CHKERRXX(perr); offset += subvec_len; } @@ -284,7 +286,7 @@ void repeat_stack_petsc_to_nat(const Vec& subvec, const Vec& stacked, const DM& PetscObjectGetComm(reinterpret_cast(subvec), &comm); PetscObjectGetComm(reinterpret_cast(stacked), &comm2); if (comm != comm2){ - throw std::runtime_error("stacked and subvec must share a communicator"); + throw InternalError("stacked and subvec must share a communicator", __FILE__, __LINE__); } integer subvec_len; @@ -296,26 +298,26 @@ void repeat_stack_petsc_to_nat(const Vec& subvec, const Vec& stacked, const DM& std::ostringstream errss; errss << "stacked length (" << stacked_len << ") not a multiple of subvec length (" << subvec_len << ")."; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } AO ao_petsctonat; // N.B this is not going to be a leak, we are just borrowing a Petsc managed // obj. PetscErrorCode perr = DMDAGetAO(subvec_dmda, &ao_petsctonat); // Destroying this would break the dmda - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Get extents of local data in subvector integer startelem, datasize; perr = VecGetOwnershipRange(subvec, &startelem, &datasize); - CHKERRABORT(comm, perr); + CHKERRXX(perr); datasize -= startelem; // Create IS for source indices in stacked array IS_unique src_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem, 1, src_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Convert with AO to map from natural to petsc ordering (do here because tgt_is is offset) perr = AOApplicationToPetscIS(ao_petsctonat, *src_is); - CHKERRABORT(comm, perr); + CHKERRXX(perr); integer stack_total = stacked_len / subvec_len; integer offset = 0; // Track offset @@ -324,17 +326,17 @@ void repeat_stack_petsc_to_nat(const Vec& subvec, const Vec& stacked, const DM& IS_unique tgt_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem + offset, 1, tgt_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Create scatterer and add to array VecScatter_unique scatterer = create_unique_vecscatter(); perr = VecScatterCreate(subvec, *src_is, stacked, *tgt_is, scatterer.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*scatterer, subvec, stacked, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*scatterer, subvec, stacked, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(comm, perr); + CHKERRXX(perr); offset += subvec_len; } @@ -347,7 +349,7 @@ void copy_nth_from_stack_nat_to_petsc(const Vec& subvec, const Vec& stacked, con PetscObjectGetComm(reinterpret_cast(subvec), &comm); PetscObjectGetComm(reinterpret_cast(stacked), &comm2); if (comm != comm2){ - throw std::runtime_error("stacked and subvec must share a communicator"); + throw InternalError("stacked and subvec must share a communicator", __FILE__, __LINE__); } integer subvec_len; @@ -360,49 +362,49 @@ void copy_nth_from_stack_nat_to_petsc(const Vec& subvec, const Vec& stacked, con std::ostringstream errss; errss << "stacked length (" << stacked_len << ") not a multiple of subvec length (" << subvec_len << ")."; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } if (n >= stack_total) { std::ostringstream errss; errss << "n must be less than stacked length / subvec length."; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } AO ao_petsctonat; // N.B this is not going to be a leak, we are just borrowing a Petsc managed // obj. PetscErrorCode perr = DMDAGetAO(subvec_dmda, &ao_petsctonat); // Destroying this would break the dmda - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Get extents of local data in subvector integer startelem, datasize; perr = VecGetOwnershipRange(subvec, &startelem, &datasize); - CHKERRABORT(comm, perr); + CHKERRXX(perr); datasize -= startelem; // Create IS for source indices in stacked array IS_unique src_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem, 1, src_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Convert with AO to map from natural to petsc ordering (do here because tgt_is is offset) // This direction because then we'll reverse the scatter perr = AOApplicationToPetscIS(ao_petsctonat, *src_is); - CHKERRABORT(comm, perr); + CHKERRXX(perr); integer offset = n*subvec_len; // Track offset IS_unique tgt_is = create_unique_is(); perr = ISCreateStride(comm, datasize, startelem + offset, 1, tgt_is.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); // Create scatterer and add to array VecScatter_unique scatterer = create_unique_vecscatter(); perr = VecScatterCreate(subvec, *src_is, stacked, *tgt_is, scatterer.get()); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterBegin(*scatterer, stacked, subvec, INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(comm, perr); + CHKERRXX(perr); perr = VecScatterEnd(*scatterer, stacked, subvec, INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(comm, perr); + CHKERRXX(perr); } diff --git a/src/pfire.cpp b/src/pfire.cpp index 9c59354..dc2bb25 100644 --- a/src/pfire.cpp +++ b/src/pfire.cpp @@ -61,7 +61,15 @@ int main(int argc, char **argv) MPI_Abort(PETSC_COMM_WORLD, -1); } - configobj->validate_config(); + try + { + configobj->validate_config(); + } + catch (const BadConfigurationError &e) + { + std::cerr << "Error: failed to parse configuration: " << e.what() << std::endl; + return -1; + } auto tstart = std::chrono::high_resolution_clock::now(); mainflow(configobj); @@ -79,12 +87,15 @@ int main(int argc, char **argv) void mainflow(std::shared_ptr config) { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + std::unique_ptr fixed; try { - fixed = Image::load_file(config->grab("fixed")); + fixed = Image::load_file(config->grab("flixed")); } - catch (std::exception &e) + catch (const pFIREExpectedError &e) { std::cerr << "Error: Failed to load fixed image: " << e.what() << std::endl; return; @@ -102,7 +113,7 @@ void mainflow(std::shared_ptr config) { moved = Image::load_file(config->grab("moved"), fixed.get()); } - catch (std::exception &e) + catch (const pFIREExpectedError &e) { std::cerr << "Error: Failed to load moved image: " << e.what() << std::endl; return; @@ -125,7 +136,7 @@ void mainflow(std::shared_ptr config) { mask = Mask::load_file(config->grab("mask"), fixed.get()); } - catch (std::exception &e) + catch (const pFIREExpectedError &e) { std::cerr << "Error: Failed to load mask: " << e.what() << std::endl; return; diff --git a/src/setup.cpp b/src/setup.cpp index 312d75a..52d6ea8 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -66,6 +66,7 @@ void pfire_setup(const std::vector& petsc_args, bool silent) // Setup terminate handler std::set_terminate(abort_with_unhandled_error); std::signal(SIGTERM, sigterm_handler); + std::signal(SIGABRT, sigterm_handler); std::vector cstrings; cstrings.resize(petsc_args.size()); @@ -76,7 +77,7 @@ void pfire_setup(const std::vector& petsc_args, bool silent) char** cstr_ptr = cstrings.data(); PetscErrorCode perr = PetscInitialize(&n_cstrings, &cstr_ptr, nullptr, nullptr); - CHKERRABORT(PETSC_COMM_WORLD, perr); + CHKERRXX(perr); int rank; MPI_Comm_rank(PETSC_COMM_WORLD, &rank); @@ -104,11 +105,11 @@ void check_comm_size_and_warn_odd() if (comm_size > 2 && comm_size % 2 == 1) { - std::cout << "!!!! WARNING !!!!\n" - << "Using an odd number of processors is not recommended.\n" - << "This makes efficient subdivision of the problem much harder and will likely " + std::cout << "\n!!!! WARNING !!!!\n" + << "\tUsing an odd number of processors is not recommended.\n" + << "\tThis makes efficient subdivision of the problem much harder and will likely " << "lead to reduced performance.\n" - << "Extreme cases may make viable partitioning impossible and cause job failure. " + << "\tExtreme cases may make viable partitioning impossible and cause job failure. " << "You have been warned!\n\n" << std::flush; } @@ -133,3 +134,5 @@ void print_welcome_message() std::cout << welcomess.str(); } + + diff --git a/src/shirtemulation.cpp b/src/shirtemulation.cpp index 5e42d6f..5f26ef4 100644 --- a/src/shirtemulation.cpp +++ b/src/shirtemulation.cpp @@ -81,13 +81,15 @@ void ShirtConfig::parse_arguments() } // now check option taking arguments - if (std::find(arg_options.cbegin(), arg_options.cend(), arg_lower) != arg_options.cend()) + if (arg_options.find(arg_lower) != arg_options.cend()) { // try to get associated option if (args_it == arguments.cend()) { // no argument, this is an error - throw std::runtime_error("missing option for argument"); + std::ostringstream errss; + errss << "missing option for argument \"" << arg_lower << "\""; + throw BadConfigurationError(errss.str()); } // grab associated option and increment iterator std::string optval = *args_it; @@ -95,8 +97,7 @@ void ShirtConfig::parse_arguments() // finally insert arg-val pair into the argument map config[arg_lower] = optval; } - else if ( - std::find(bool_options.cbegin(), bool_options.cend(), arg_lower) != bool_options.cend()) + else if (bool_options.find(arg_lower) != bool_options.cend()) { // insert arg-val pair into argument map config[arg_lower] = "true"; @@ -108,7 +109,7 @@ void ShirtConfig::parse_arguments() errbuf << "Unhandled arguments: "; std::copy( arguments.cbegin(), arguments.cend(), std::ostream_iterator(errbuf, " ")); - throw std::runtime_error(errbuf.str()); + throw BadConfigurationError(errbuf.str()); } } } diff --git a/src/shirtloader.cpp b/src/shirtloader.cpp index 76d9bf6..effd904 100644 --- a/src/shirtloader.cpp +++ b/src/shirtloader.cpp @@ -50,13 +50,13 @@ ShIRTLoader::ShIRTLoader(const std::string &path, MPI_Comm comm) { _shape = read_and_validate_image_header(fh); } - catch (const std::runtime_error &) + catch (const InvalidLoaderError &) { try { _shape = read_and_validate_mask_header(fh); } - catch (const std::runtime_error &) + catch (const InvalidLoaderError &) { _shape[0] = -1; } @@ -94,7 +94,7 @@ intvector ShIRTLoader::read_and_validate_image_header(const MPI_File &fh) // Currently only handle grayscale images if (headerdata[3] != 1) { - throw std::runtime_error("Color images not currently supported"); + throw InvalidLoaderError("Color images not currently supported"); } if (mpi_err == MPI_SUCCESS && read_count == image_header_bytes) @@ -107,7 +107,7 @@ intvector ShIRTLoader::read_and_validate_image_header(const MPI_File &fh) } else { - throw std::runtime_error("Not a valid shirt image"); + throw InvalidLoaderError("Not a valid shirt image"); } } } @@ -140,7 +140,7 @@ intvector ShIRTLoader::read_and_validate_mask_header(const MPI_File &fh) } else { - throw std::runtime_error("Not a valid shirt image"); + throw InvalidLoaderError("Not a valid shirt image"); } } } @@ -163,8 +163,7 @@ void ShIRTLoader::copy_scaled_chunk( copy_chunk_mask(data, subsize, starts); break; default: - throw std::runtime_error( - "ShirtLoader attempted to load from non-shirt file type. This is a bug"); + throw InternalError("ShirtLoader attempted to load from non-shirt file type. This is a bug", __FILE__, __LINE__); } } @@ -207,7 +206,7 @@ void ShIRTLoader::copy_chunk_image( MPI_Error_string(mpi_err, mpi_err_str.data(), &str_size); mpi_err_str.resize(str_size); errss << "[Rank " << rank << "] Failed to set view: " << mpi_err_str; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } MPI_Status read_status; @@ -216,7 +215,7 @@ void ShIRTLoader::copy_chunk_image( MPI_Get_count(&read_status, image_data_mpi_type, &read_count); if (mpi_err != MPI_SUCCESS || read_count != dcount) { - throw std::runtime_error("Failed to read data chunk."); + throw InternalError("Failed to read data chunk.", __FILE__, __LINE__); } floating *rankdata = &data[starts[2]][starts[1]][starts[0]]; @@ -266,7 +265,7 @@ void ShIRTLoader::copy_chunk_mask( MPI_Error_string(mpi_err, mpi_err_str.data(), &str_size); mpi_err_str.resize(str_size); errss << "[Rank " << rank << "] Failed to set view: " << mpi_err_str; - throw std::runtime_error(errss.str()); + throw InternalError(errss.str(), __FILE__, __LINE__); } MPI_Status read_status; @@ -275,7 +274,7 @@ void ShIRTLoader::copy_chunk_mask( MPI_Get_count(&read_status, mask_data_mpi_type, &read_count); if (mpi_err != MPI_SUCCESS || read_count != dcount) { - throw std::runtime_error("Failed to read data chunk."); + throw InternalError("Failed to read data chunk.", __FILE__, __LINE__); } floating *rankdata = &data[starts[2]][starts[1]][starts[0]]; diff --git a/src/versioning.cpp b/src/versioning.cpp new file mode 100644 index 0000000..66ea451 --- /dev/null +++ b/src/versioning.cpp @@ -0,0 +1,66 @@ +// +// Copyright 2019 University of Sheffield +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#ifdef USE_DCMTK +#include +#endif //USE_DCMTK + +#ifdef USE_OIIO +#include +#endif //USE_OIIO + +#include "types.hpp" + +std::string get_version_string_petsc() +{ +#if PETSC_VERSION_MINOR > 7 + integer major, minor, subminor; + PetscGetVersionNumber(&major, &minor, &subminor, nullptr); + + return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(subminor); +#else + return std::to_string(PETSC_VERSION_MAJOR) + "." + std::to_string(PETSC_VERSION_MINOR) + + "." + std::to_string(PETSC_VERSION_SUBMINOR); +#endif + +} + +std::string get_version_string_boost() +{ + // See "Boost Informational Macros" section of boost::config docs + integer major = BOOST_VERSION / 100000; + integer minor = (BOOST_VERSION / 100) % 1000; + integer subminor = BOOST_VERSION % 100; + + return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(subminor); +} + +#ifdef USE_DCMTK +std::string get_version_string_dcmtk() +{ + return std::string(PACKAGE_VERSION); +} +#endif //USE_DCMTK + +#ifdef USE_OIIO +std::string get_version_string_oiio() +{ + return std::to_string(OIIO_VERSION_MAJOR) + "." + std::to_string(OIIO_VERSION_MINOR) + "." + + std::to_string(OIIO_VERSION_PATCH); +} +#endif //USE_OIIO diff --git a/src/versioning.hpp b/src/versioning.hpp new file mode 100644 index 0000000..14482ea --- /dev/null +++ b/src/versioning.hpp @@ -0,0 +1,27 @@ +// +// Copyright 2019 University of Sheffield +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +std::string get_version_string_petsc(); +std::string get_version_string_boost(); + +#ifdef USE_DCMTK +std::string get_version_string_dcmtk(); +#endif //USE_DCMTK + +#ifdef USE_OIIO +std::string get_version_string_oiio(); +#endif //USE_OIIO diff --git a/src/workspace.cpp b/src/workspace.cpp index ab7c1be..a0005d8 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -29,21 +29,21 @@ WorkSpace::WorkSpace(const Image& image, const Map& map) Vec_unique tmp_vec = create_unique_vec(); PetscErrorCode perr = VecDuplicate(*image.global_vec(), tmp_vec.get()); debug_creation(*tmp_vec, std::string("grads_") + std::to_string(static_cast(idim))); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); m_globaltmps.push_back(std::move(tmp_vec)); } // create local vector to allow gradient calculation m_localtmp = create_unique_vec(); PetscErrorCode perr = VecDuplicate(*image.local_vec(), m_localtmp.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // create "global" vector for stack compatible with basis matrix // should be compatible with all map bases of this size m_stacktmp = create_unique_vec(); perr = MatCreateVecs(*map.basis(), nullptr, m_stacktmp.get()); debug_creation(*m_stacktmp, "workspace vector"); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); create_reordering_scatterers(); create_nonreordering_scatterers(); @@ -58,15 +58,15 @@ void WorkSpace::reallocate_ephemeral_workspace(const Map& map) m_delta = create_unique_vec(); m_rhs = create_unique_vec(); perr = VecDuplicate(*map.m_displacements, m_delta.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*m_delta, std::string("solution_storage_") + std::to_string(ephemeral_count)); perr = VecSet(*m_delta, 0.); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecDuplicate(*map.m_displacements, m_rhs.get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); debug_creation(*m_delta, std::string("rhs_storage_") + std::to_string(ephemeral_count)); perr = VecSet(*m_rhs, 0.); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } void WorkSpace::scatter_stacked_to_grads() @@ -75,10 +75,10 @@ void WorkSpace::scatter_stacked_to_grads() { PetscErrorCode perr = VecScatterBegin( *m_r_scatterers[idim], *m_stacktmp, *m_globaltmps[idim], INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd( *m_r_scatterers[idim], *m_stacktmp, *m_globaltmps[idim], INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } } @@ -88,10 +88,10 @@ void WorkSpace::scatter_grads_to_stacked() { PetscErrorCode perr = VecScatterBegin( *m_r_scatterers[idim], *m_globaltmps[idim], *m_stacktmp, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd( *m_r_scatterers[idim], *m_globaltmps[idim], *m_stacktmp, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } } @@ -101,10 +101,10 @@ void WorkSpace::duplicate_single_grad_to_stacked(size_t idx) { PetscErrorCode perr = VecScatterBegin( *m_r_scatterers[idim], *m_globaltmps[idx], *m_stacktmp, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd( *m_r_scatterers[idim], *m_globaltmps[idx], *m_stacktmp, INSERT_VALUES, SCATTER_FORWARD); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } } @@ -114,10 +114,10 @@ void WorkSpace::scatter_stacked_to_grads_noreorder() { PetscErrorCode perr = VecScatterBegin( *m_nr_scatterers[idim], *m_stacktmp, *m_globaltmps[idim], INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); perr = VecScatterEnd( *m_nr_scatterers[idim], *m_stacktmp, *m_globaltmps[idim], INSERT_VALUES, SCATTER_REVERSE); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); } } @@ -129,25 +129,25 @@ void WorkSpace::create_nonreordering_scatterers() // Get extents of local data in grad array integer startelem, datasize; PetscErrorCode perr = VecGetOwnershipRange(*pp_grad, &startelem, &datasize); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); datasize -= startelem; // Create IS for source indices in stacked array, keep in vector for memory management m_iss.push_back(create_unique_is()); IS* p_src_is = m_iss.back().get(); // grab a temp copy to avoid vector accesses below perr = ISCreateStride(m_comm, datasize, startelem, 1, p_src_is); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); m_iss.push_back(create_unique_is()); IS* p_tgt_is = m_iss.back().get(); // grab a temp copy to avoid vector accesses below perr = ISCreateStride(m_comm, datasize, startelem + offset, 1, p_tgt_is); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Create scatterer and add to array m_nr_scatterers.push_back(create_unique_vecscatter()); perr = VecScatterCreate(*pp_grad, *p_src_is, *m_stacktmp, *p_tgt_is, m_nr_scatterers.back().get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); offset += m_size; } @@ -158,7 +158,7 @@ void WorkSpace::create_reordering_scatterers() AO ao_petsctonat; // N.B this is not going to be a leak, we are just borrowing a Petsc managed // obj. PetscErrorCode perr = DMDAGetAO(*m_dmda, &ao_petsctonat); // Destroying this would break the dmda - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); integer offset = 0; // Track offset for (auto&& pp_grad : m_globaltmps) @@ -166,28 +166,28 @@ void WorkSpace::create_reordering_scatterers() // Get extents of local data in grad array integer startelem, datasize; perr = VecGetOwnershipRange(*pp_grad, &startelem, &datasize); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); datasize -= startelem; // Create IS for source indices in stacked array, keep in vector for memory management m_iss.push_back(create_unique_is()); IS* p_src_is = m_iss.back().get(); // grab a temp copy to avoid vector accesses below perr = ISCreateStride(m_comm, datasize, startelem, 1, p_src_is); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Convert with AO to map from petsc to natural ordering (do here because tgt_is is offset) perr = AOApplicationToPetscIS(ao_petsctonat, *m_iss.back()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); m_iss.push_back(create_unique_is()); IS* p_tgt_is = m_iss.back().get(); // grab a temp copy to avoid vector accesses below perr = ISCreateStride(m_comm, datasize, startelem + offset, 1, p_tgt_is); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); // Create scatterer and add to array m_r_scatterers.push_back(create_unique_vecscatter()); perr = VecScatterCreate(*pp_grad, *p_src_is, *m_stacktmp, *p_tgt_is, m_r_scatterers.back().get()); - CHKERRABORT(m_comm, perr); + CHKERRXX(perr); offset += m_size; }