位于路径src/OpenFOAM/primitives/Scalar
标量,其实就是浮点数。但是浮点数具有不同的精度,最终文件将根据宏的设置决定程序使用哪种精度
文件依赖关系如下:
注意这里大小写的scalar
是两个文件,大写的Scalar
是各个精度的浮点数的依赖文件,而这些具体的精度的实现又是小写的scalar
的实现
floatScalar
这里给出其中一个文件的具体实现方式,其余的类似
头文件内容如下:
typedef float floatScalar;
定义最大最小的浮点数
floatScalarVGreat floatScalarVSmall
floatScalarSmall floatScalarGreat
floatScalarRootVGreat floatScalarRootVSmall
floatScalarRootGreat floatScalarRootSmall
给定函数readScalar(const char* buf, floatScalar& s)
{
char* endPtr;
s = strtof(buf, &endPtr);
return (*endPtr == '\\0');
}
//注意这里很重要
#define Scalar floatScalar
#define ScalarVGreat floatScalarVGreat
#define ScalarVSmall floatScalarVSmall
#define ScalarRootVGreat floatScalarRootVGreat
#define ScalarRootVSmall floatScalarRootVSmall
#define readScalar readFloatScalar
其他若干基础函数
.C
文件的内容如下
#define Scalar floatScalar
#define ScalarVGreat floatScalarVGreat
#define ScalarVSmall floatScalarVSmall
#define ScalarRootVGreat floatScalarRootVGreat
#define ScalarRootVSmall floatScalarRootVSmall
#define readScalar readFloatScalar
#include "Scalar.C" //这里添加了大写的Scalar.C
#undef Scalar
#undef ScalarVSmall
#undef ScalarVSmall
#undef ScalarRootVGreat
#undef ScalarRootVSmall
#undef readScalar
实际上这些宏定义在Scalar.C
中被使用,因为不同的浮点精度要实现相同的功能,所以通过将类名称统一成Scalar
,就可以给出统一的代码。比如说,如果是doubleScalar
,那么.C
文件中的内容为:
#define Scalar doubleScalar
#define ScalarVGreat doubleScalarVGreat
#define ScalarVSmall doubleScalarVSmall
#define ScalarRootVGreat doubleScalarRootVGreat
#define ScalarRootVSmall doubleScalarRootVSmall
#define readScalar readDoubleScalar
#include "Scalar.C"
#undef Scalar
#undef ScalarVGreat
#undef ScalarVSmall
#undef ScalarRootVGreat
#undef ScalarRootVSmall
#undef readScalar
Scalar
头文件内容如下:
class pTraits<Scalar> //pTraits是用来帮基础类实现构造函数和文件流函数的模板
{
Scalar p_; //Scalar在前面已经宏定义为对应的类型
public:
typedef Scalar cmptType;
typedef label labelType;
static const direction dim = 3; //- Dimensionality of space
static const direction rank = 0; //- Rank of Scalar is 0
static const direction nComponents = 1; //- Number of components in Scalar is 1
若干支持性的成员变量
构造函数和析构函数
};
sign minMod pow dot等等功能性函数
readScalar >> <<等文件流操作
而.C
文件中只给出了对应的函数的实现以及成员变量的初始化
const char* const pTraits<Scalar>::typeName = "scalar";
const Scalar pTraits<Scalar>::zero = 0.0;
const Scalar pTraits<Scalar>::one = 1.0;
const Scalar pTraits<Scalar>::min = -ScalarVGreat;
const Scalar pTraits<Scalar>::max = ScalarVGreat;
const Scalar pTraits<Scalar>::rootMin = -ScalarRootVGreat;
const Scalar pTraits<Scalar>::rootMax = ScalarRootVGreat;
其他非inline函数的实现
相当于所有的浮点精度有相同的功能,这些功能通过将类型统一定义为Scalar
然后统一实现
这里有一个我不太明白的点,这里的标量在openFOAM是指单个的数据,所以
static const direction nComponents = 1; //- Number of components in Scalar is 1
但是这里还给出了维度,这个代表三维空间吗?等后续理解了再来修改
static const direction dim = 3; //- Dimensionality of space
scalar
其实这个文件是我们平时在其他程序中添加的头文件,头文件内容如下:
#if defined(WM_SP)
// Define scalar as a float
namespace Foam
{
typedef floatScalar scalar;
static const scalar great = floatScalarGreat;
static const scalar rootGreat = floatScalarRootGreat;
static const scalar vGreat = floatScalarVGreat;
static const scalar rootVGreat = floatScalarRootVGreat;
static const scalar small = floatScalarSmall;
static const scalar rootSmall = floatScalarRootSmall;
static const scalar vSmall = floatScalarVSmall;
static const scalar rootVSmall = floatScalarRootVSmall;
}
#elif defined(WM_DP)
// Define scalar as a double
namespace Foam
{
typedef doubleScalar scalar;
....
}
#elif defined(WM_LP)
// Define scalar as a long double
namespace Foam
{
typedef longDoubleScalar scalar;
...
}
#else
#error "Precision not set, please set either WM_SP, WM_DP or WM_LP"
#endif
//- Deprecated limit constant for backward-compatibility
namespace Foam
{
static const scalar GREAT = great;
static const scalar ROOTGREAT = rootGreat;
static const scalar VGREAT = vGreat;
static const scalar ROOTVGREAT = rootVGreat;
static const scalar SMALL = small;
static const scalar ROOTSMALL = rootSmall;
static const scalar VSMALL = vSmall;
static const scalar ROOTVSMALL = rootVSmall;
}
若干Gamma函数相关的函数
而.C
文件则是其中非inline
函数的实现。
就是说根据我们定义的宏为WM_SP
还是WM_DP
还是WM_LP
,决定我们最终使用哪个精度作为scalar
的最终精度。文件只不过另外添加了一些函数
文件流的操作
最后讲讲scalar.H
中的一个文件流操作,这个非常常用,所以单独拿出来说:
scalar readScalar(Istream& is)
{
scalar rs;
is >> rs;
return rs;
}
我们提供一个文件流,这里创建了一个标量rs
,然后将文件流>>
进rs
,注意这里的>>
进行了操作符重定义。然后将得到的标量rs
返回。