Commit 28a865b6 authored by COULAUD Olivier's avatar COULAUD Olivier

Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/scalfmm/scalfmm

# By bramas (2) and Marc-Alexandre Espiaut (1)
# Via Marc-Alexandre Espiaut
* 'master' of git+ssh://scm.gforge.inria.fr//gitroot/scalfmm/scalfmm:
  Adding suggestions
  Create a kernel utester for one over R for now
  Create new functions to work with template very easily
parents 1f972ab7 34721e01
I don't know if theses ideas are relevant since ScallFMM is only supposed to be a library, but as an everyday UNIX // GNU/Linux user, some things struck me.
* About the -f / -infile / -fin argument
For some reason, all tests have similar arguments that differs in name from one to another.
I suggest that this should be standardized as "-if" for "input file" and "-of" for "output file" just like in the dd UNIX command.
Therefore we won't spend anymore time wondering what the proper argument for the tool is.
* About arguments in general
Maybe it would be clearer to use one or two letters when using a single hyphen-minus and full words when using a double hyphen-minus.
Here's an exemple to make my idea clearer:
-h | --help
-v | --verbose
-d | --depth
-sd | --subdepth
-if | --input
-of | --output
etc...
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FTEMPLATE_HPP
#define FTEMPLATE_HPP
///////////////////////////////////////////////////////////////////////////////////////
/// This file provide useful method to work with template.
/// It provide solution in order to build several methods
/// and run them accordingly to a given condition.
/// We recommand to look at the testTemplateExample.cpp in order
/// to see the usage.
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
/// FForAll : Compile all and exec all
///////////////////////////////////////////////////////////////////////////////////////
#include <functional>
namespace FForAll{
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, bool IsNotOver, typename... Args>
struct Evaluator{
static void Run(Args... args){
Func::template For<CurrentIter>(args...);
Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(args...);
}
};
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{
static void Run(Args... args){
}
};
template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
void For(Args... args){
Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(args...);
}
}
///////////////////////////////////////////////////////////////////////////////////////
/// FRunIf : Compile all and exec only one (if the template variable is equal to
/// the first variable)
///////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
namespace FRunIf{
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, bool IsNotOver, typename... Args>
struct Evaluator{
static void Run(IterType value, Args... args){
if(CurrentIter == value){
Func::template Run<CurrentIter>(args...);
}
else{
Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(value, args...);
}
}
};
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{
static void Run(IterType value, Args... args){
std::cout << __FUNCTION__ << " no matching value found\n";
}
};
template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
void Run(IterType value, Args... args){
Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(value, args...);
}
}
///////////////////////////////////////////////////////////////////////////////////////
/// FRunIfFunctional : Compile all and exec only those whose respect a condition
///////////////////////////////////////////////////////////////////////////////////////
namespace FRunIfFunctional{
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, bool IsNotOver, typename... Args>
struct Evaluator{
static void Run(std::function<bool(IterType)> test, Args... args){
if(test(CurrentIter)){
Func::template Run<CurrentIter>(args...);
}
Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(test, args...);
}
};
template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{
static void Run(std::function<bool(IterType)> test, Args... args){
}
};
template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep,
class Func, typename... Args>
void Run(std::function<bool(IterType)> test, Args... args){
Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(test, args...);
}
}
#endif // FTEMPLATE_HPP
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
/** This file gives an example of the template helper usage.
*
**/
#include "../../Src/Utils/FTemplate.hpp"
#include <iostream>
struct RunContainer{
template <const int P>
static void For(double mydouble, int myint){
std::cout << "For >> P = " << P << " mydouble " << mydouble << " myint " << myint << "\n";
}
template <const int P>
static void Run(double mydouble, int myint){
std::cout << "Run >> P = " << P << " mydouble " << mydouble << " myint " << myint << "\n";
}
template <const int P>
static void Run(){
std::cout << "Run without param >> P = " << P << "\n";
}
};
// Compile with g++ -std=c++11 main.cpp -o test.exe
int main(){
// This will call the For method (maybe several times)
FForAll::For<int, 0, 20, 1, RunContainer>(45.4, 55);
// This will call the Run method
FRunIf::Run<int, 0, 20, 1, RunContainer>(3, 45.4, 55);
// Should not run, because 21 is out of the compiled interval
FRunIf::Run<int, 0, 20, 1, RunContainer>(21, 45.4, 55);
// Call the Run method with no param
FRunIf::Run<int, 0, 20, 1, RunContainer>(18);
// Call the Run method with no param for odd P
FRunIfFunctional::Run<int, 0, 20, 1, RunContainer>([&](int p){ return p&1;});
// Call the Run method with params for even P
FRunIfFunctional::Run<int, 0, 20, 1, RunContainer>([&](int p){ return !(p&1);}, 45.4, 55);
return 0;
}
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FUKERNELTESTER_HPP
#define FUKERNELTESTER_HPP
#include "ScalFmmConfig.h"
#include "../Src/Utils/FGlobal.hpp"
#include "FUTester.hpp"
#include "../Src/Containers/FOctree.hpp"
#include "../Src/Files/FFmaGenericLoader.hpp"
#include "../Src/Core/FFmmAlgorithm.hpp"
#include "../Src/Utils/FPoint.hpp"
#include <memory>
#include <functional>
/**
* This class test a usual configuration against the direct computation.
* Subclasses must provide the templates and a function to build
* a kernel.
* For Example :
* RunTest<CellClass,ContainerClass,KernelClass,LeafClass,OctreeClass,FmmClass>(
* [&](int NbLevels, FReal boxWidth, FPoint centerOfBox){
* return std::unique_ptr<KernelClass>(new KernelClass(NbLevels, boxWidth, centerOfBox));
* });
* But it can be a static method or function.
*/
template <class TestClass>
class FUKernelTester : public FUTester<TestClass> {
public:
// We should state that we are using FUTester Methods
using FUTester<TestClass>::Print;
using FUTester<TestClass>::uassert;
// The run function is performing the test for the given configuration
template <class CellClass, class ContainerClass, class KernelClass,
class LeafClass, class OctreeClass, class FmmClass>
void RunTest(std::function<std::unique_ptr<KernelClass>(int NbLevels, FReal boxWidth, FPoint centerOfBox)> GetKernelFunc) {
//
// Load particles
//
if(sizeof(FReal) == sizeof(float) ) {
std::cerr << "No input data available for Float "<< std::endl;
exit(EXIT_FAILURE);
}
const std::string parFile( (sizeof(FReal) == sizeof(float))?
"Test/DirectFloat.bfma":
"UTest/DirectDouble.bfma");
//
std::string filename(SCALFMMDataPath+parFile);
//
FFmaGenericLoader loader(filename);
Print("Number of particles:");
Print(loader.getNumberOfParticles());
const int NbLevels = 4;
const int SizeSubLevels = 2;
FSize nbParticles = loader.getNumberOfParticles() ;
FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[nbParticles];
loader.fillParticle(particles,nbParticles);
//
// Create octree
OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
// Insert particle in the tree
//
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
tree.insert(particles[idxPart].getPosition() , idxPart, particles[idxPart].getPhysicalValue() );
}
//
/////////////////////////////////////////////////////////////////////////////////////////////////
// Run FMM computation
/////////////////////////////////////////////////////////////////////////////////////////////////
Print("Fmm...");
std::unique_ptr<KernelClass> kernels(GetKernelFunc(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()));
FmmClass algo(&tree,kernels.get());
algo.execute();
//
FReal energy= 0.0 , energyD = 0.0 ;
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compute direct energy
/////////////////////////////////////////////////////////////////////////////////////////////////
for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){
energyD += particles[idx].getPotential()*particles[idx].getPhysicalValue() ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compare
/////////////////////////////////////////////////////////////////////////////////////////////////
Print("Compute Diff...");
FMath::FAccurater potentialDiff;
FMath::FAccurater fx, fy, fz;
{ // Check that each particle has been summed with all other
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues();
const FReal*const forcesX = leaf->getTargets()->getForcesX();
const FReal*const forcesY = leaf->getTargets()->getForcesY();
const FReal*const forcesZ = leaf->getTargets()->getForcesZ();
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
const FVector<int>& indexes = leaf->getTargets()->getIndexes();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const int indexPartOrig = indexes[idxPart];
potentialDiff.add(particles[indexPartOrig].getPotential(),potentials[idxPart]);
fx.add(particles[indexPartOrig].getForces()[0],forcesX[idxPart]);
fy.add(particles[indexPartOrig].getForces()[1],forcesY[idxPart]);
fz.add(particles[indexPartOrig].getForces()[2],forcesZ[idxPart]);
energy += potentials[idxPart]*physicalValues[idxPart];
}
});
}
delete[] particles;
// Print for information
Print("Potential diff is = ");
printf(" Pot L2Norm %e\n",potentialDiff.getL2Norm());
printf(" Pot RL2Norm %e\n",potentialDiff.getRelativeL2Norm());
printf(" Pot RMSError %e\n",potentialDiff.getRMSError());
Print("Fx diff is = ");
printf(" Fx L2Norm %e\n",fx.getL2Norm());
printf(" Fx RL2Norm %e\n",fx.getRelativeL2Norm());
printf(" Fx RMSError %e\n",fx.getRMSError());
Print("Fy diff is = ");
printf(" Fy L2Norm %e\n",fy.getL2Norm());
printf(" Fy RL2Norm %e\n",fy.getRelativeL2Norm());
printf(" Fy RMSError %e\n",fy.getRMSError());
Print("Fz diff is = ");
printf(" Fz L2Norm %e\n",fz.getL2Norm());
printf(" Fz RL2Norm %e\n",fz.getRelativeL2Norm());
printf(" Fz RMSError %e\n",fz.getRMSError());
FReal L2error = (fx.getRelativeL2Norm()*fx.getRelativeL2Norm() + fy.getRelativeL2Norm()*fy.getRelativeL2Norm() + fz.getRelativeL2Norm() *fz.getRelativeL2Norm() );
printf(" Total L2 Force Error= %e\n",FMath::Sqrt(L2error)) ;
printf(" Energy Error = %.12e\n",FMath::Abs(energy-energyD));
printf(" Energy FMM = %.12e\n",FMath::Abs(energy));
printf(" Energy DIRECT = %.12e\n",FMath::Abs(energyD));
// Assert
const FReal MaximumDiffPotential = FReal(9e-3);
const FReal MaximumDiffForces = FReal(9e-2);
Print("Test1 - Error Relative L2 norm Potential ");
uassert(potentialDiff.getRelativeL2Norm() < MaximumDiffPotential); //1
Print("Test2 - Error RMS L2 norm Potential ");
uassert(potentialDiff.getRMSError() < MaximumDiffPotential); //2
Print("Test3 - Error Relative L2 norm FX ");
uassert(fx.getRelativeL2Norm() < MaximumDiffForces); //3
Print("Test4 - Error RMS L2 norm FX ");
uassert(fx.getRMSError() < MaximumDiffForces); //4
Print("Test5 - Error Relative L2 norm FY ");
uassert(fy.getRelativeL2Norm() < MaximumDiffForces); //5
Print("Test6 - Error RMS L2 norm FY ");
uassert(fy.getRMSError() < MaximumDiffForces); //6
Print("Test7 - Error Relative L2 norm FZ ");
uassert(fz.getRelativeL2Norm() < MaximumDiffForces); //8
Print("Test8 - Error RMS L2 norm FZ ");
uassert(fz.getRMSError() < MaximumDiffForces); //8
Print("Test9 - Error Relative L2 norm F ");
uassert(L2error < MaximumDiffForces); //9 Total Force
Print("Test10 - Relative error Energy ");
uassert(FMath::Abs(energy-energyD) /energyD< MaximumDiffPotential); //10 Total Energy
}
/** If memstas is running print the memory used */
void PostTest() override {
if( FMemStats::controler.isUsed() ){
std::cout << "Memory used at the end "
<< FMemStats::controler.getCurrentAllocated()
<< " Bytes (" << FMemStats::controler.getCurrentAllocatedMB() << "MB)\n";
std::cout << "Max memory used "
<< FMemStats::controler.getMaxAllocated()
<< " Bytes (" << FMemStats::controler.getMaxAllocatedMB() << "MB)\n";
std::cout << "Total memory used "
<< FMemStats::controler.getTotalAllocated()
<< " Bytes (" << FMemStats::controler.getTotalAllocatedMB() << "MB)\n";
}
}
};
#endif // FUKERNELTESTER_HPP
......@@ -18,187 +18,24 @@
// @FUSE_BLAS
// ================
#include "ScalFmmConfig.h"
#include "Utils/FGlobal.hpp"
#include "FUKernelTester.hpp"
#include "Containers/FOctree.hpp"
#include "../Src/Components/FSimpleLeaf.hpp"
#include "Files/FFmaGenericLoader.hpp"
#include "../Src/Kernels/Chebyshev/FChebCell.hpp"
#include "../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp"
#include "../Src/Kernels/Chebyshev/FChebKernel.hpp"
#include "../Src/Kernels/Chebyshev/FChebSymKernel.hpp"
#include "Core/FFmmAlgorithm.hpp"
#include "FUTester.hpp"
#include "Components/FSimpleLeaf.hpp"
#include "Kernels/Chebyshev/FChebCell.hpp"
#include "Kernels/Interpolation/FInterpMatrixKernel.hpp"
#include "Kernels/Chebyshev/FChebKernel.hpp"
#include "Kernels/Chebyshev/FChebSymKernel.hpp"
#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp"
#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp"
/*
In this test we compare the Chebyschev fmm results and the direct results.
*/
/** the test class
*
*/
class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
///////////////////////////////////////////////////////////
// The tests!
///////////////////////////////////////////////////////////
template <class CellClass, class ContainerClass, class KernelClass, class MatrixKernelClass,
class LeafClass, class OctreeClass, class FmmClass>
void RunTest() {
//
// Load particles
//
if(sizeof(FReal) == sizeof(float) ) {
std::cerr << "No input data available for Float "<< std::endl;
exit(EXIT_FAILURE);
}
const std::string parFile( (sizeof(FReal) == sizeof(float))?
"Test/DirectFloat.bfma":
"UTest/DirectDouble.bfma");
//
std::string filename(SCALFMMDataPath+parFile);
//
FFmaGenericLoader loader(filename);
Print("Number of particles:");
Print(loader.getNumberOfParticles());
const int NbLevels = 4;
const int SizeSubLevels = 2;
FSize nbParticles = loader.getNumberOfParticles() ;
FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[nbParticles];
loader.fillParticle(particles,nbParticles);
//
// Create octree
OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
// Insert particle in the tree
//
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
tree.insert(particles[idxPart].getPosition() , idxPart, particles[idxPart].getPhysicalValue() );
}
//
/////////////////////////////////////////////////////////////////////////////////////////////////
// Run FMM computation
/////////////////////////////////////////////////////////////////////////////////////////////////
Print("Fmm...");
KernelClass kernels(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox());
FmmClass algo(&tree,&kernels);
algo.execute();
//
FReal energy= 0.0 , energyD = 0.0 ;
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compute direct energy
/////////////////////////////////////////////////////////////////////////////////////////////////
for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){
energyD += particles[idx].getPotential()*particles[idx].getPhysicalValue() ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compare
/////////////////////////////////////////////////////////////////////////////////////////////////
Print("Compute Diff...");
FMath::FAccurater potentialDiff;
FMath::FAccurater fx, fy, fz;
{ // Check that each particle has been summed with all other
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues();
const FReal*const forcesX = leaf->getTargets()->getForcesX();
const FReal*const forcesY = leaf->getTargets()->getForcesY();
const FReal*const forcesZ = leaf->getTargets()->getForcesZ();
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
const FVector<int>& indexes = leaf->getTargets()->getIndexes();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const int indexPartOrig = indexes[idxPart];
potentialDiff.add(particles[indexPartOrig].getPotential(),potentials[idxPart]);
fx.add(particles[indexPartOrig].getForces()[0],forcesX[idxPart]);
fy.add(particles[indexPartOrig].getForces()[1],forcesY[idxPart]);
fz.add(particles[indexPartOrig].getForces()[2],forcesZ[idxPart]);
energy += potentials[idxPart]*physicalValues[idxPart];
}
});
}
delete[] particles;
// Print for information
Print("Potential diff is = ");
printf(" Pot L2Norm %e\n",potentialDiff.getL2Norm());
printf(" Pot RL2Norm %e\n",potentialDiff.getRelativeL2Norm());
printf(" Pot RMSError %e\n",potentialDiff.getRMSError());
Print("Fx diff is = ");
printf(" Fx L2Norm %e\n",fx.getL2Norm());
printf(" Fx RL2Norm %e\n",fx.getRelativeL2Norm());
printf(" Fx RMSError %e\n",fx.getRMSError());
Print("Fy diff is = ");
printf(" Fy L2Norm %e\n",fy.getL2Norm());
printf(" Fy RL2Norm %e\n",fy.getRelativeL2Norm());
printf(" Fy RMSError %e\n",fy.getRMSError());
Print("Fz diff is = ");
printf(" Fz L2Norm %e\n",fz.getL2Norm());
printf(" Fz RL2Norm %e\n",fz.getRelativeL2Norm());
printf(" Fz RMSError %e\n",fz.getRMSError());
FReal L2error = (fx.getRelativeL2Norm()*fx.getRelativeL2Norm() + fy.getRelativeL2Norm()*fy.getRelativeL2Norm() + fz.getRelativeL2Norm() *fz.getRelativeL2Norm() );
printf(" Total L2 Force Error= %e\n",FMath::Sqrt(L2error)) ;
printf(" Energy Error = %.12e\n",FMath::Abs(energy-energyD));
printf(" Energy FMM = %.12e\n",FMath::Abs(energy));
printf(" Energy DIRECT = %.12e\n",FMath::Abs(energyD));
// Assert
const FReal MaximumDiffPotential = FReal(9e-3);
const FReal MaximumDiffForces = FReal(9e-2);
Print("Test1 - Error Relative L2 norm Potential ");
uassert(potentialDiff.getRelativeL2Norm() < MaximumDiffPotential); //1
Print("Test2 - Error RMS L2 norm Potential ");
uassert(potentialDiff.getRMSError() < MaximumDiffPotential); //2
Print("Test3 - Error Relative L2 norm FX ");
uassert(fx.getRelativeL2Norm() < MaximumDiffForces); //3
Print("Test4 - Error RMS L2 norm FX ");
uassert(fx.getRMSError() < MaximumDiffForces); //4
Print("Test5 - Error Relative L2 norm FY ");
uassert(fy.getRelativeL2Norm() < MaximumDiffForces); //5
Print("Test6 - Error RMS L2 norm FY ");
uassert(fy.getRMSError() < MaximumDiffForces); //6
Print("Test7 - Error Relative L2 norm FZ ");
uassert(fz.getRelativeL2Norm() < MaximumDiffForces); //8
Print("Test8 - Error RMS L2 norm FZ ");
uassert(fz.getRMSError() < MaximumDiffForces); //8
Print("Test9 - Error Relative L2 norm F ");
uassert(L2error < MaximumDiffForces); //9 Total Force
Print("Test10 - Relative error Energy ");
uassert(FMath::Abs(energy-energyD) /energyD< MaximumDiffPotential); //10 Total Energy
}
/** If memstas is running print the memory used */
void PostTest() {
if( FMemStats::controler.isUsed() ){
std::cout << "Memory used at the end " << FMemStats::controler.getCurrentAllocated()
<< " Bytes (" << FMemStats::controler.getCurrentAllocatedMB() << "MB)\n";
std::cout << "Max memory used " << FMemStats::controler.getMaxAllocated()
<< " Bytes (" << FMemStats::controler.getMaxAllocatedMB() << "MB)\n";
std::cout << "Total memory used " << FMemStats::controler.getTotalAllocated()
<< " Bytes (" << FMemStats::controler.getTotalAllocatedMB() << "MB)\n";
}
}
class TestChebyshevDirect : public FUKernelTester<TestChebyshevDirect> {
///////////////////////////////////////////////////////////
// Set the tests!
......@@ -216,7 +53,10 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
typedef FChebKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass;
// run test
RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>();
RunTest<CellClass,ContainerClass,KernelClass,LeafClass,OctreeClass,FmmClass>(
[&](int NbLevels, FReal boxWidth, FPoint centerOfBox){
return std::unique_ptr<KernelClass>(new KernelClass(NbLevels, boxWidth, centerOfBox));
});
}
/** TestChebSymKernel */
......@@ -230,7 +70,10 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass;
// run test
RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>();
RunTest<CellClass,ContainerClass,KernelClass,LeafClass,OctreeClass,FmmClass>(
[&](int NbLevels, FReal boxWidth, FPoint centerOfBox){
return std::unique_ptr<KernelClass>(new KernelClass(NbLevels, boxWidth, centerOfBox));
});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment