changed: use a common implementation for setNoDims()

add a helper template and specialize this
for the types instead. preparation for upcoming changes
to workaround c++'s inability to partially specialize
member functions
This commit is contained in:
Arne Morten Kvarving 2023-09-20 22:51:13 +02:00
parent abbf8a2dd1
commit 09cf3e55e5
3 changed files with 122 additions and 35 deletions

View File

@ -119,6 +119,63 @@ std::vector<std::string> splitComps (const std::string& functions,
return comps;
}
/*!
\brief Helper template to get size and dimension of a return type.
*/
template<class ArgType>
std::pair<size_t,size_t> getNoDims(size_t psize);
/*!
\brief Template specialization for Vec3.
*/
template<>
std::pair<size_t,size_t> getNoDims<Vec3>(size_t psize)
{
return {psize, psize};
}
/*!
\brief Template specialization for Tensor.
*/
template<>
std::pair<size_t,size_t> getNoDims<Tensor>(size_t psize)
{
size_t nsd = 0;
if (psize > 8)
nsd = 3;
else if (psize > 3)
nsd = 2;
else if (psize > 0)
nsd = 1;
return {nsd, nsd*nsd};
}
/*!
\brief Template specialization for SymmTensor.
*/
template<>
std::pair<size_t,size_t> getNoDims<SymmTensor>(size_t psize)
{
size_t nsd = 0;
if (psize > 5)
nsd = 3;
else if (psize > 2)
nsd = 2;
else if (psize > 0)
nsd = 1;
return {nsd, psize == 4 ? 4 : (nsd+1)*nsd/2};
}
}
@ -402,6 +459,13 @@ Ret EvalMultiFunction<ParentFunc,Ret>::evaluate (const Vec3& X) const
}
template <class ParentFunc, class Ret>
void EvalMultiFunction<ParentFunc,Ret>::setNoDims ()
{
std::tie(nsd, this->ncmp) = getNoDims<Ret>(this->p.size());
}
template<class ParentFunc, class Ret>
Ret EvalMultiFunction<ParentFunc,Ret>::deriv (const Vec3& X, int dir) const
{
@ -424,34 +488,6 @@ Ret EvalMultiFunction<ParentFunc,Ret>::dderiv (const Vec3& X, int d1, int d2) co
}
template<>
void TensorFuncExpr::setNoDims ()
{
if (p.size() > 8)
nsd = 3;
else if (p.size() > 3)
nsd = 2;
else if (p.size() > 0)
nsd = 1;
ncmp = nsd*nsd;
}
template<>
void STensorFuncExpr::setNoDims ()
{
if (p.size() > 5)
nsd = 3;
else if (p.size() > 2)
nsd = 2;
else if (p.size() > 0)
nsd = 1;
ncmp = p.size() == 4 ? 4 : (nsd+1)*nsd/2;
}
template class EvalMultiFunction<VecFunc,Vec3>;
template class EvalMultiFunction<TensorFunc,Tensor>;
template class EvalMultiFunction<STensorFunc,SymmTensor>;

View File

@ -214,9 +214,12 @@ public:
func->setParam(name, value);
}
//! \brief Returns number of spatial dimension.
size_t getNoSpaceDim() const { return nsd; }
protected:
//! \brief Sets the number of spatial dimensions (default implementation).
void setNoDims() { ParentFunc::ncmp = nsd = p.size(); }
void setNoDims();
//! \brief Evaluates the function expressions.
Ret evaluate(const Vec3& X) const override;
@ -229,10 +232,4 @@ using TensorFuncExpr = EvalMultiFunction<TensorFunc,Tensor>;
//! Symmetric tensor-valued function expression
using STensorFuncExpr = EvalMultiFunction<STensorFunc,SymmTensor>;
//! \brief Specialization for tensor functions.
template<> void TensorFuncExpr::setNoDims();
//! \brief Specialization for symmetric tensor functions.
template<> void STensorFuncExpr::setNoDims();
#endif

View File

@ -66,6 +66,24 @@ TEST(TestVecFunc, Evaluate)
}
TEST(TestVecFuncExpr, NumDimensions)
{
const char* func1 = "x";
const char* func2 = "x | y";
const char* func3 = "x | y | z";
VecFuncExpr f1(func1);
EXPECT_EQ(f1.getNoSpaceDim(), 1);
EXPECT_EQ(f1.dim(), 1);
VecFuncExpr f2(func2);
EXPECT_EQ(f2.getNoSpaceDim(), 2);
EXPECT_EQ(f2.dim(), 2);
VecFuncExpr f3(func3);
EXPECT_EQ(f3.getNoSpaceDim(), 3);
EXPECT_EQ(f3.dim(), 3);
}
TEST(TestTensorFunc, Evaluate)
{
const char* func = "sin(x) | cos (y) | exp(z) | sin(x)*cos(y)";
@ -381,6 +399,24 @@ TEST(TestTensorFunction, Hessian3D)
}
TEST(TestTensorFuncExpr, NumDimensions)
{
const char* func1 = "x";
const char* func2 = "x | y | z | x";
const char* func3 = "x | y | z | x | y | z | x | y | z";
TensorFuncExpr f1(func1);
EXPECT_EQ(f1.getNoSpaceDim(), 1);
EXPECT_EQ(f1.dim(), 1);
TensorFuncExpr f2(func2);
EXPECT_EQ(f2.getNoSpaceDim(), 2);
EXPECT_EQ(f2.dim(), 4);
TensorFuncExpr f3(func3);
EXPECT_EQ(f3.getNoSpaceDim(), 3);
EXPECT_EQ(f3.dim(), 9);
}
TEST(TestSTensorFunc, Evaluate2D)
{
const char* func = "sin(x) | cos (y) | exp(z)";
@ -639,6 +675,24 @@ TEST(TestSTensorFunction, Gradient3DFD)
}
TEST(TestSTensorFuncExpr, NumDimensions)
{
const char* func1 = "x";
const char* func2 = "x | y | z";
const char* func3 = "x | y | z | x | y | z";
STensorFuncExpr f1(func1);
EXPECT_EQ(f1.getNoSpaceDim(), 1);
EXPECT_EQ(f1.dim(), 1);
STensorFuncExpr f2(func2);
EXPECT_EQ(f2.getNoSpaceDim(), 2);
EXPECT_EQ(f2.dim(), 3);
STensorFuncExpr f3(func3);
EXPECT_EQ(f3.getNoSpaceDim(), 3);
EXPECT_EQ(f3.dim(), 6);
}
TEST(TestEvalFunction, ExtraParam)
{
EvalFunction f("x*foo");