In class Mesh/ParMesh:
* Move the serial implementation of UniformRefinement3D to a new
method: UniformRefinement3D_base. The implementations of the virtual
method UniformRefinement3D (which now have no parameters) use the
new UniformRefinement3D_base method.
* In UniformRefinement3D_base, implemented two algorithms for choosing
how to split the middle octahedron when refining a tetrahedron by
cutting off its four corner tets. (These four tets have the same
shape as the original tet and half the edge-length.) The choice of
the algorithm is hard-coded in a const variable for now.
* Add an optional parameter to UniformRefinement which is used to
choose how to refine tet-only meshes: the default choice is to use
the new algorithm defined by UniformRefinement3D; the second option
is to use the old default - call LocalRefinement (marking all
elements) to perform 3 levels of bisection. The new algorithm
always produces elements with better shape (aspect ratio) than the
old default (at least for the meshes in the data/ directory and a
few other meshes).
* Make the method Finalize virtual - its implementation in parallel
requires updates in the ParMesh data.
* Add a consistency check in ParMesh::ReorientTetMesh that verifies
the assumption made in the method about the update of the shared
triangles.
* Simplify implementation of some methods in class ParMesh by
separating common code in a new protected method: FinalizeParTopo.
Other updates:
* In the examples and miniapps, when using a tet-only mesh which is
first refined uniformly and then locally, it is now necessary to
call the method Mesh::Finalize(true) (which is now virtual) in order
to mark the elements for local refinement after the uniform
refinement.
* In example 12p, use better random seed values.
* In examples 3/3p, add a sample run with order=2 on a tet mesh - this
will test the methods {Mesh,ParMesh}::ReorientTetMesh. Previously,
these were only tested by one sample run in example 4p.
* In the mesh-explorer miniapp, add a refinement option to perform
uniform refinement of tet-only meshes using bisection.
* In the MFEM_LOCATION macro print the <file> and <line> location
using a standard format: <file>:<line>, as used by most compilers
when reporting warnings and errors.
* Remove FIXME comments about mesh format v1.0.1.
142 lines
5.0 KiB
C++
142 lines
5.0 KiB
C++
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
|
|
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
|
|
// reserved. See file COPYRIGHT for details.
|
|
//
|
|
// This file is part of the MFEM library. For more information and source code
|
|
// availability see http://mfem.org.
|
|
//
|
|
// MFEM is free software; you can redistribute it and/or modify it under the
|
|
// terms of the GNU Lesser General Public License (as published by the Free
|
|
// Software Foundation) version 2.1 dated February 1999.
|
|
|
|
#ifndef MFEM_ERROR_HPP
|
|
#define MFEM_ERROR_HPP
|
|
|
|
#include "../config/config.hpp"
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
/// Action to take when MFEM encounters an error.
|
|
enum ErrorAction
|
|
{
|
|
MFEM_ERROR_ABORT = 0, /**<
|
|
Abort execution using abort() or MPI_Abort(). This is the default error
|
|
action when the build option MFEM_USE_EXCEPTIONS is set to NO. */
|
|
MFEM_ERROR_THROW /**<
|
|
Throw an ErrorException. Requires the build option MFEM_USE_EXCEPTIONS=YES
|
|
in which case it is also the default error action. */
|
|
};
|
|
|
|
/// Set the action MFEM takes when an error is encountered.
|
|
void set_error_action(ErrorAction action);
|
|
/// Get the action MFEM takes when an error is encountered.
|
|
ErrorAction get_error_action();
|
|
|
|
#ifdef MFEM_USE_EXCEPTIONS
|
|
/** @brief Exception class thrown when MFEM encounters an error and the current
|
|
ErrorAction is set to MFEM_ERROR_THROW. */
|
|
class ErrorException: public std::exception
|
|
{
|
|
private:
|
|
std::string msg;
|
|
public:
|
|
explicit ErrorException(const std::string & in_msg) : msg(in_msg) { }
|
|
virtual ~ErrorException() throw() { }
|
|
virtual const char* what() const throw();
|
|
};
|
|
#endif
|
|
|
|
void mfem_backtrace(int mode = 0, int depth = -1);
|
|
|
|
/** @brief Function called when an error is encountered. Used by the macros
|
|
MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY. */
|
|
void mfem_error(const char *msg = NULL);
|
|
|
|
/// Function called by the macro MFEM_WARNING.
|
|
void mfem_warning(const char *msg = NULL);
|
|
|
|
}
|
|
|
|
#ifndef _MFEM_FUNC_NAME
|
|
#ifndef _MSC_VER
|
|
// This is nice because it shows the class and method name
|
|
#define _MFEM_FUNC_NAME __PRETTY_FUNCTION__
|
|
// This one is C99 standard.
|
|
//#define _MFEM_FUNC_NAME __func__
|
|
#else
|
|
// for Visual Studio C++
|
|
#define _MFEM_FUNC_NAME __FUNCSIG__
|
|
#endif
|
|
#endif
|
|
|
|
#define MFEM_LOCATION \
|
|
"\n ... in function: " << _MFEM_FUNC_NAME << \
|
|
"\n ... in file: " << __FILE__ << ':' << __LINE__ << '\n'
|
|
|
|
// Common error message and abort macro
|
|
#define _MFEM_MESSAGE(msg, warn) \
|
|
{ \
|
|
std::ostringstream mfemMsgStream; \
|
|
mfemMsgStream << std::setprecision(16); \
|
|
mfemMsgStream << std::setiosflags(std::ios_base::scientific); \
|
|
mfemMsgStream << msg << MFEM_LOCATION; \
|
|
if (!(warn)) \
|
|
mfem::mfem_error(mfemMsgStream.str().c_str()); \
|
|
else \
|
|
mfem::mfem_warning(mfemMsgStream.str().c_str()); \
|
|
}
|
|
|
|
// Outputs lots of useful information and aborts.
|
|
// For all of these functions, "msg" is pushed to an ostream, so you can
|
|
// write useful (if complicated) error messages instead of writing
|
|
// out to the screen first, then calling abort. For example:
|
|
// MFEM_ABORT( "Unknown geometry type: " << type );
|
|
#define MFEM_ABORT(msg) _MFEM_MESSAGE("MFEM abort: " << msg, 0)
|
|
|
|
// Does a check, and then outputs lots of useful information if the test fails
|
|
#define MFEM_VERIFY(x, msg) \
|
|
if (!(x)) \
|
|
{ \
|
|
_MFEM_MESSAGE("Verification failed: (" \
|
|
<< #x << ") is false:\n --> " << msg, 0); \
|
|
}
|
|
|
|
// Use this if the only place your variable is used is in ASSERTs
|
|
// For example, this code snippet:
|
|
// int err = MPI_Reduce(ldata, maxdata, 5, MPI_INT, MPI_MAX, 0, MyComm);
|
|
// MFEM_CONTRACT_VAR(err);
|
|
// MFEM_ASSERT( err == 0, "MPI_Reduce gave an error with length "
|
|
// << ldata );
|
|
#define MFEM_CONTRACT_VAR(x) if (0 && &x == &x){}
|
|
|
|
// Now set up some optional checks, but only if the right flags are on
|
|
#ifdef MFEM_DEBUG
|
|
|
|
#define MFEM_ASSERT(x, msg) \
|
|
if (!(x)) \
|
|
{ \
|
|
_MFEM_MESSAGE("Assertion failed: (" \
|
|
<< #x << ") is false:\n --> " << msg, 0); \
|
|
}
|
|
|
|
// A macro that exposes its argument in debug mode only.
|
|
#define MFEM_DEBUG_DO(x) x
|
|
|
|
#else
|
|
|
|
// Get rid of all this code, since we're not checking.
|
|
#define MFEM_ASSERT(x, msg)
|
|
|
|
// A macro that exposes its argument in debug mode only.
|
|
#define MFEM_DEBUG_DO(x)
|
|
|
|
#endif
|
|
|
|
// Generate a warning message - always generated, regardless of MFEM_DEBUG.
|
|
#define MFEM_WARNING(msg) _MFEM_MESSAGE("MFEM Warning: " << msg, 1)
|
|
|
|
#endif
|