Commit fbb1f394 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#1340 Introduce a catch mechanism in the three Petsc Snes internal function I...

#1340 Introduce a catch mechanism in the three Petsc Snes internal function I have to define when using Petsc Newton. The issue is that if an exception is thrown in any of these, I got a message regarding uncaught exception due to C++ abi problem. This message was printed at the very end of the program, but still hindered dramatically the readability of the output. I have in fact here introduced a macro MOREFEM_NO_TRAP_SNES_EXCEPTION: if it is not defined in each of these three functions exceptions are caught systematically and 'converted' into an arbitrary Petsc error code; if not the old behaviour is kept. The latter might be the right choice for release as try/catch in an oft called function might be expensive in runtime.
parent 6fdd9cf6
......@@ -1407,6 +1407,7 @@
BEC72C432053EB6500E71849 /* QuasiIncompressibleSecondPiolaKirchhoffStressTensor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BEC72C402053EB6500E71849 /* QuasiIncompressibleSecondPiolaKirchhoffStressTensor.hpp */; };
BEC91E0E1F0676B40034626D /* Format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE11C7C61CC51F6F00C09D51 /* Format.cpp */; };
BECA4BE11B1757F400DC7265 /* libOperators.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BECA4B941B1756DE00DC7265 /* libOperators.a */; };
BECB2E0D213FFBAC0093CB05 /* SnesMacro.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BECB2E0A213FFBAC0093CB05 /* SnesMacro.hpp */; };
BED13353206519C800A3B0AA /* Penalization.hxx in Headers */ = {isa = PBXBuildFile; fileRef = BED13351206519C700A3B0AA /* Penalization.hxx */; };
BED13354206519C800A3B0AA /* Penalization.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BED13352206519C800A3B0AA /* Penalization.hpp */; };
BED793B11D1AD75900492784 /* HyperelasticLaw.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BED793AE1D1AD75900492784 /* HyperelasticLaw.hpp */; };
......@@ -4688,6 +4689,7 @@
BEC77E9E1DDDC39E00F8B444 /* Model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Model.hpp; sourceTree = "<group>"; };
BEC77E9F1DDDC39E00F8B444 /* Model.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Model.hxx; sourceTree = "<group>"; };
BECA4B941B1756DE00DC7265 /* libOperators.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOperators.a; sourceTree = BUILT_PRODUCTS_DIR; };
BECB2E0A213FFBAC0093CB05 /* SnesMacro.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SnesMacro.hpp; sourceTree = "<group>"; };
BECB556219D5AF5B00CC4828 /* GaussQuadratureFormula.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GaussQuadratureFormula.hpp; sourceTree = "<group>"; };
BECB556319D5AF5B00CC4828 /* GaussQuadratureFormula.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GaussQuadratureFormula.hxx; sourceTree = "<group>"; };
BECCE67818EAE16A0043D5DB /* QuadraturePoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QuadraturePoint.cpp; sourceTree = "<group>"; };
......@@ -9292,6 +9294,7 @@
BE4B17CF1AA5AB0E0073516A /* Print.hxx */,
BE9FE83F18CE0A6900177F79 /* Viewer.cpp */,
BE9FE84018CE0A6900177F79 /* Viewer.hpp */,
BECB2E0A213FFBAC0093CB05 /* SnesMacro.hpp */,
BE9FE82318CE0A6900177F79 /* Exceptions */,
);
path = Petsc;
......@@ -11472,6 +11475,7 @@
BE5E406E1AAA088E007F8B1E /* Environment.hpp in Headers */,
BE76F2691D7D609E0061B50E /* GlobalVectorTemporary.hpp in Headers */,
BE76F2561D7D5DE90061B50E /* CSRPattern.hxx in Headers */,
BECB2E0D213FFBAC0093CB05 /* SnesMacro.hpp in Headers */,
BE3D12C01D9B1FFB00F900F5 /* KspConvergenceReason.hpp in Headers */,
BE8B5F8120778D1A00DC005E /* StringPair.hxx in Headers */,
BE5B6F8C1C3C16E9004A0284 /* MatrixOperations.hpp in Headers */,
......@@ -14,6 +14,7 @@
# include "ThirdParty/Wrappers/Petsc/Print.hpp"
# include "ThirdParty/Wrappers/Petsc/Solver/Snes.hpp"
# include "ThirdParty/Wrappers/Petsc/SnesMacro.hpp"
namespace MoReFEM
......
......@@ -25,41 +25,45 @@ namespace MoReFEM
PetscErrorCode SnesInterface<VariationalFormulationT>
::Function(SNES snes, Vec a_evaluation_state, Vec a_residual, void* context_as_void)
{
static_cast<void>(snes);
static_cast<void>(a_residual);
MOREFEM_TRAP_SNES_EXCEPTION_TRY
{
static_cast<void>(snes);
static_cast<void>(a_residual);
// \a context_as_void is in fact the VariationalFormulation object.
assert(context_as_void);
VariationalFormulationT* formulation_ptr = static_cast<VariationalFormulationT*>(context_as_void);
// \a context_as_void is in fact the VariationalFormulation object.
assert(context_as_void);
VariationalFormulationT* formulation_ptr = static_cast<VariationalFormulationT*>(context_as_void);
auto& formulation = *formulation_ptr;
auto& formulation = *formulation_ptr;
#ifndef NDEBUG
{
std::string desc;
#ifndef NDEBUG
{
std::string desc;
namespace Petsc = Wrappers::Petsc;
namespace Petsc = Wrappers::Petsc;
const auto& numbering_subset = formulation.GetNumberingSubset();
const auto& numbering_subset = formulation.GetNumberingSubset();
const bool is_same = Petsc::AreEqual(Petsc::Vector(a_residual, false),
formulation.GetSystemRhs(numbering_subset),
1.e-12,
desc,
__FILE__, __LINE__);
const bool is_same = Petsc::AreEqual(Petsc::Vector(a_residual, false),
formulation.GetSystemRhs(numbering_subset),
1.e-12,
desc,
__FILE__, __LINE__);
if (!is_same)
{
std::cerr << "Bug in SNES implementation: third argument of snes function implemention is expected "
"to be the residual, which is born in VariationalFormulationT by the attribute RHS(). It is not the case "
"here.\n" << desc << std::endl;
assert(false);
if (!is_same)
{
std::cerr << "Bug in SNES implementation: third argument of snes function implemention is expected "
"to be the residual, which is born in VariationalFormulationT by the attribute RHS(). It is not the case "
"here.\n" << desc << std::endl;
assert(false);
}
}
}
#endif // NDEBUG
#endif // NDEBUG
formulation.SnesUpdate(a_evaluation_state);
formulation.ComputeResidual();
formulation.SnesUpdate(a_evaluation_state);
formulation.ComputeResidual();
}
MOREFEM_TRAP_SNES_EXCEPTION_CATCH(SnesFunction)
return 0;
}
......@@ -70,17 +74,21 @@ namespace MoReFEM
::Jacobian(SNES snes, Vec evaluation_state, Mat jacobian,
Mat preconditioner, void* context_as_void)
{
static_cast<void>(snes);
static_cast<void>(jacobian);
static_cast<void>(preconditioner);
static_cast<void>(evaluation_state);
MOREFEM_TRAP_SNES_EXCEPTION_TRY
{
static_cast<void>(snes);
static_cast<void>(jacobian);
static_cast<void>(preconditioner);
static_cast<void>(evaluation_state);
// \a context_as_void is in fact the VariationalFormulation object.
assert(context_as_void);
VariationalFormulationT* formulation_ptr = static_cast<VariationalFormulationT*>(context_as_void);
// \a context_as_void is in fact the VariationalFormulation object.
assert(context_as_void);
VariationalFormulationT* formulation_ptr = static_cast<VariationalFormulationT*>(context_as_void);
auto& formulation = *formulation_ptr;
formulation.ComputeTangent();
auto& formulation = *formulation_ptr;
formulation.ComputeTangent();
}
MOREFEM_TRAP_SNES_EXCEPTION_CATCH(SnesJacobian)
return 0;
}
......@@ -91,32 +99,37 @@ namespace MoReFEM
PetscErrorCode SnesInterface<VariationalFormulationT>
::Viewer(SNES snes, PetscInt its, PetscReal norm, void* context_as_void)
{
static_cast<void>(snes);
assert(context_as_void);
MOREFEM_TRAP_SNES_EXCEPTION_TRY
{
static_cast<void>(snes);
assert(context_as_void);
const VariationalFormulationT* variational_formulation_ptr =
static_cast<const VariationalFormulationT*>(context_as_void);
const VariationalFormulationT* variational_formulation_ptr =
static_cast<const VariationalFormulationT*>(context_as_void);
assert(!(!variational_formulation_ptr));
assert(!(!variational_formulation_ptr));
const auto& variational_formulation = *variational_formulation_ptr;
const auto& variational_formulation = *variational_formulation_ptr;
const auto& vector = variational_formulation.GetSnesEvaluationState();
const auto& vector = variational_formulation.GetSnesEvaluationState();
const PetscReal evaluation_state_min = vector.Min(__FILE__, __LINE__).second;
const PetscReal evaluation_state_max = vector.Max(__FILE__, __LINE__).second;
const PetscReal evaluation_state_min = vector.Min(__FILE__, __LINE__).second;
const PetscReal evaluation_state_max = vector.Max(__FILE__, __LINE__).second;
std::ostringstream oconv;
oconv << VariationalFormulationT::ClassName() << " --- Norm is %14.12e and extrema are %8.6e and %8.6e\n";
std::ostringstream oconv;
oconv << VariationalFormulationT::ClassName() << " --- Norm is %14.12e and extrema are %8.6e and %8.6e\n";
Wrappers::Petsc::PrintMessageOnFirstProcessor(oconv.str().c_str(),
variational_formulation.GetMpi(),
__FILE__, __LINE__,
its,
norm,
evaluation_state_min,
evaluation_state_max
);
}
MOREFEM_TRAP_SNES_EXCEPTION_CATCH(SnesViewer)
Wrappers::Petsc::PrintMessageOnFirstProcessor(oconv.str().c_str(),
variational_formulation.GetMpi(),
__FILE__, __LINE__,
its,
norm,
evaluation_state_min,
evaluation_state_max
);
return 0;
}
......
......@@ -87,8 +87,6 @@ namespace MoReFEM
const auto& dI3dC =
invariant_holder.GetFirstDerivativeWrtCauchyGreen(invariant_holder_type::invariants_first_derivative_index::dI3dC);
throw Exception("FAKE", __FILE__, __LINE__);
// Note: one of these quantities might be infinite... but in this case this infinite (or a resulting
// nan) will be assembled into a Petsc matrix or vector, which will in turn handle properly
// the case. See #1317 to know more about it.
......
//! \file
//
//
// SnesMacro.hpp
// MoReFEM
//
// Created by sebastien on 05/09/2018.
//Copyright © 2018 Inria. All rights reserved.
//
#ifndef MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_SNES_MACRO_HPP_
# define MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_SNES_MACRO_HPP_
# ifdef MOREFEM_NO_TRAP_SNES_EXCEPTION
# define MOREFEM_TRAP_SNES_EXCEPTION_TRY
# define MOREFEM_TRAP_SNES_EXCEPTION_CATCH(Snes)
# else // MOREFEM_NO_TRAP_SNES_EXCEPTION
# define MOREFEM_TRAP_SNES_EXCEPTION_TRY try
# define MOREFEM_TRAP_SNES_EXCEPTION_CATCH(Snes) \
catch(const std::exception& e) \
{ \
std::cerr << "Exception caught in the Petsc Snes definition: " << e.what() << std::endl; \
return PETSC_ERR_MIN_VALUE; \
}
# endif // MOREFEM_NO_TRAP_SNES_EXCEPTION
#endif // MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_SNES_MACRO_HPP_
......@@ -186,7 +186,7 @@ namespace MoReFEM
preconditioner_matrix.Internal(),
GetSnesJacobian(),
context);
if (error_code)
throw ExceptionNS::Exception(error_code, "SNESSetJacobian", invoking_file, invoking_line);
......
......@@ -9,6 +9,7 @@ target_sources(${MOREFEM_UTILITIES}
"${CMAKE_CURRENT_LIST_DIR}/Petsc.hpp"
"${CMAKE_CURRENT_LIST_DIR}/Print.hpp"
"${CMAKE_CURRENT_LIST_DIR}/Print.hxx"
"${CMAKE_CURRENT_LIST_DIR}/SnesMacro.hpp"
"${CMAKE_CURRENT_LIST_DIR}/Viewer.hpp"
)
......
......@@ -14,5 +14,5 @@ LIBRARY_SEARCH_PATHS = $(LIBRARY_SEARCH_PATHS_COMMON) ${THIRD_PARTY_LIBRARY_DIR}
GCC_OPTIMIZATION_LEVEL = 3
GCC_PREPROCESSOR_DEFINITIONS = SELDON_WITH_LAPACK SELDON_WITH_BLAS NDEBUG SELDON_WITH_COMPILED_LIBRARY SELDON_WITHOUT_TO_STR_CHECKDIM
GCC_PREPROCESSOR_DEFINITIONS = SELDON_WITH_LAPACK SELDON_WITH_BLAS NDEBUG SELDON_WITH_COMPILED_LIBRARY SELDON_WITHOUT_TO_STR_CHECKDIM MOREFEM_NO_TRAP_SNES_EXCEPTION
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment