根据编译时是否定义了HAVE_MPI(意味着是否支持MPI并行编程接口)来选择性地实例化不同的模板类。这种方式常用于处理需要在不同编译环境下表现出不同行为的代码。
FlexibleSolver_impl.hpp
#define INSTANTIATE_FLEXIBLESOLVER_OP(Operator)
template class Dune::FlexibleSolver;
template Dune::FlexibleSolver::FlexibleSolver(Operator& op,
const Comm& comm,
const Opm::PropertyTree& prm,
const std::function<typename Operator::domain_type()>& weightsCalculator,
std::size_t pressureIndex);
#define INSTANTIATE_FLEXIBLESOLVER(N)
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM);
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW);
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpM);
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpW);
#else // HAVE_MPI
#define INSTANTIATE_FLEXIBLESOLVER_OP(Operator)
template class Dune::FlexibleSolver;
#define INSTANTIATE_FLEXIBLESOLVER(N)
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM);
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW);
#endif // HAVE_MPI
#endif
解析:
INSTANTIATE_FLEXIBLESOLVER_OP(Operator)宏:这个宏负责实例化Dune::FlexibleSolver模板类。对于不同的Operator类型,这个宏会生成模板类的实例化代码。如果定义了HAVE_MPI,则它还会为Dune::FlexibleSolver类生成一个构造函数的实例化,该构造函数接受特定类型的参数。
INSTANTIATE_FLEXIBLESOLVER(N)宏:这个宏通过调用INSTANTIATE_FLEXIBLESOLVER_OP宏来实例化特定的操作类型。它根据N的值为SeqOpM、SeqOpW、ParOpM和ParOpW类型(如果定义了HAVE_MPI)或者只为SeqOpM和SeqOpW类型(如果未定义HAVE_MPI)实例化FlexibleSolver。
条件编译指令#else和#endif:这些指令与前面的#ifdef HAVE_MPI或#if defined(HAVE_MPI)配合使用,允许代码根据HAVE_MPI宏的定义与否选择性地编译。这种方法允许开发者为支持MPI的环境和不支持MPI的环境编写特定的代码。
如果HAVE_MPI被定义,意味着环境支持MPI,并行操作类型ParOpM和ParOpW也将被实例化,以及为FlexibleSolver类生成更为复杂的构造函数实例。
如果HAVE_MPI未被定义,仅序列操作类型SeqOpM和SeqOpW将被实例化,且FlexibleSolver类的构造函数实例化将是简化版本的。
FlexibleSolver6.cpp:
#include “config.h”
#include <opm/simulators/linalg/FlexibleSolver_impl.hpp>
INSTANTIATE_FLEXIBLESOLVER(6);
//宏通常用于代码的复用,可以看作是一种简单的函数或模板。
//这个特定的宏调用看起来是在实例化某种名为FlexibleSolver的模板或类的一个或多个实例,其中6可能是传递给该宏的参数,表明了某种类型的编号、尺寸或者其他配置信息。