mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Feature single precision solve type
This commit is contained in:
committed by
Andrew Heather
parent
f2eb3e1cee
commit
2d080ff331
@ -24,6 +24,10 @@ License
|
||||
Description
|
||||
Simple field tests
|
||||
|
||||
Test use of Kahan/Neumaier to extend precision for when running SPDP
|
||||
mode. Conclusion is that it is easier/quicker to run these summation
|
||||
loops as double precision (i.e. solveScalar).
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "primitiveFields.H"
|
||||
@ -32,6 +36,116 @@ Description
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, class CombineOp, class ResultType>
|
||||
void sumNeumaier
|
||||
(
|
||||
const UList<Type>& vals,
|
||||
const CombineOp& cop,
|
||||
ResultType& result
|
||||
)
|
||||
{
|
||||
// Neumaier version of Kahan
|
||||
ResultType sum = Zero;
|
||||
ResultType c = Zero;
|
||||
for (const Type& vali : vals)
|
||||
{
|
||||
ResultType val;
|
||||
cop(val, vali);
|
||||
|
||||
const ResultType t = sum + val;
|
||||
|
||||
for
|
||||
(
|
||||
direction cmpt = 0;
|
||||
cmpt < pTraits<ResultType>::nComponents;
|
||||
cmpt++
|
||||
)
|
||||
{
|
||||
if (mag(sum[cmpt]) >= mag(val[cmpt]))
|
||||
{
|
||||
// If sum is bigger, low-order digits of input[i] are lost.
|
||||
c[cmpt] += (sum[cmpt] - t[cmpt]) + val[cmpt];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else low-order digits of sum are lost.
|
||||
c[cmpt] += (val[cmpt] - t[cmpt]) + sum[cmpt];
|
||||
}
|
||||
}
|
||||
sum = t;
|
||||
}
|
||||
result = sum + c;
|
||||
}
|
||||
|
||||
|
||||
template<class CombineOp, class ResultType>
|
||||
void sumNeumaier
|
||||
(
|
||||
const UList<scalar>& vals,
|
||||
const CombineOp& cop,
|
||||
ResultType& result
|
||||
)
|
||||
{
|
||||
// Neumaier version of Kahan
|
||||
ResultType sum = Zero;
|
||||
ResultType c = Zero;
|
||||
for (const scalar vali : vals)
|
||||
{
|
||||
ResultType val;
|
||||
cop(val, vali);
|
||||
|
||||
const ResultType t = sum + val;
|
||||
if (mag(sum) >= mag(val))
|
||||
{
|
||||
// If sum is bigger, low-order digits of input[i] are lost.
|
||||
c += (sum - t) + val;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else low-order digits of sum are lost.
|
||||
c += (val - t) + sum;
|
||||
}
|
||||
sum = t;
|
||||
}
|
||||
result = sum + c;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Type mySum(const UList<Type>& f)
|
||||
{
|
||||
typedef typename Foam::typeOfSolve<Type>::type solveType;
|
||||
|
||||
solveType Sum = Zero;
|
||||
|
||||
if (f.size())
|
||||
{
|
||||
sumNeumaier(f, eqOp<solveType>(), Sum);
|
||||
}
|
||||
|
||||
return Type(Sum);
|
||||
}
|
||||
|
||||
|
||||
//- The sumSqr always adds only positive numbers. Here there can never be any
|
||||
// cancellation of truncation errors.
|
||||
template<class Type>
|
||||
typename outerProduct1<Type>::type mySumSqr(const UList<Type>& f)
|
||||
{
|
||||
typedef typename outerProduct1<solveScalar>::type prodType;
|
||||
|
||||
prodType result = Zero;
|
||||
|
||||
if (f.size())
|
||||
{
|
||||
sumNeumaier(f, eqSqrOp<prodType>(), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -63,6 +177,71 @@ int main(int argc, char *argv[])
|
||||
|
||||
Info<< "negated: " << lfield << nl;
|
||||
|
||||
|
||||
// Summation (compile in SPDP)
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pout.precision(16);
|
||||
Sout.precision(16);
|
||||
|
||||
const scalar SMALLS(1e-6);
|
||||
const vector SMALLV(SMALLS, SMALLS, SMALLS);
|
||||
const scalar GREATS(1e6);
|
||||
const vector GREATV(GREATS, GREATS, GREATS);
|
||||
|
||||
// scalarField summation
|
||||
{
|
||||
scalarField sfield(10, SMALLS);
|
||||
|
||||
sfield[8] = GREATS;
|
||||
sfield[9] = -sfield[8];
|
||||
Info<< "scalarField:" << sfield.size() << nl
|
||||
<< " sum :" << sum(sfield) << nl
|
||||
<< " corrected:" << mySum(sfield) << endl;
|
||||
}
|
||||
// vectorField summation
|
||||
{
|
||||
vectorField vfield(10, SMALLV);
|
||||
|
||||
vfield[8] = GREATV;
|
||||
vfield[9] = -vfield[8];
|
||||
Info<< "vectorField:" << vfield.size() << nl
|
||||
<< " sum :" << sum(vfield) << nl
|
||||
<< " corrected:" << mySum(vfield) << endl;
|
||||
}
|
||||
// sphericalTensorField summation
|
||||
{
|
||||
sphericalTensorField tfield(10, SMALLS);
|
||||
|
||||
tfield[8] = GREATS;
|
||||
tfield[9] = -tfield[8];
|
||||
Info<< "sphericalTensorField:" << tfield.size() << nl
|
||||
<< " sum :" << sum(tfield) << nl
|
||||
<< " corrected:" << mySum(tfield) << endl;
|
||||
}
|
||||
// symmTensorField summation
|
||||
{
|
||||
symmTensorField tfield(10, SMALLS*symmTensor::I);
|
||||
|
||||
tfield[8] = GREATS*symmTensor::I;
|
||||
tfield[9] = -tfield[8];
|
||||
Info<< "symmTensorField:" << tfield.size() << nl
|
||||
<< " sum :" << sum(tfield) << nl
|
||||
<< " corrected:" << mySum(tfield) << endl;
|
||||
}
|
||||
// tensorField summation
|
||||
{
|
||||
tensorField tfield(10, SMALLS*tensor::I);
|
||||
|
||||
tfield[8] = GREATS*tensor::I;
|
||||
tfield[9] = -tfield[8];
|
||||
Info<< "tensorField:" << tfield.size() << nl
|
||||
<< " sum :" << sum(tfield) << nl
|
||||
<< " corrected:" << mySum(tfield) << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user