/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2012 University of Bonn. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder 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 License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* LinkedCell_ModelUnitTest.cpp
*
* Created on: Nov 17, 2011
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
using namespace std;
#include
#include
#include
#include
#include "Box.hpp"
#include "CodePatterns/Assert.hpp"
#include "CodePatterns/Log.hpp"
#include "LinearAlgebra/RealSpaceMatrix.hpp"
#include "LinkedCell/LinkedCell.hpp"
#include "LinkedCell/LinkedCell_Model.hpp"
#include "LinkedCell/LinkedCell_Model_changeModel.hpp"
#include "LinkedCell/LinkedCell_Model_LinkedCellArrayCache.hpp"
#include "LinkedCell/LinkedCell_Model_Update.hpp"
#include "LinkedCell/PointCloudAdaptor.hpp"
#include "LinkedCell/unittests/defs.hpp"
#include "World.hpp"
#include "WorldTime.hpp"
#include "LinkedCell_ModelUnitTest.hpp"
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
/********************************************** Test classes **************************************/
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( LinkedCell_ModelTest );
void LinkedCell_ModelTest::setUp()
{
// failing asserts should be thrown
ASSERT_DO(Assert::Throw);
setVerbosity(3);
// create diag(20.) matrix
RealSpaceMatrix BoxM;
BoxM.setIdentity();
BoxM *= DOMAINLENGTH;
// create Box with this matrix
domain = new Box(BoxM);
// create LinkedCell structure with this Box
LC = new LinkedCell::LinkedCell_Model(EDGELENGTH, *domain);
// create a list of nodes and add to LCImpl
std::vector< Vector > VectorList;
for (size_t i=0;i<((size_t)floor(NUMBERCELLS));++i)
VectorList.push_back(Vector((double)i*EDGELENGTH,(double)i*EDGELENGTH,(double)i*EDGELENGTH));
CPPUNIT_ASSERT_EQUAL( ((size_t)floor(NUMBERCELLS)), VectorList.size() );
for (size_t i=0;isetName(std::string("Walker")+toString(i));
Walker->setPosition(VectorList[i]);
NodeList.insert(Walker);
}
CPPUNIT_ASSERT_EQUAL( VectorList.size(), NodeList.size() );
}
void LinkedCell_ModelTest::tearDown()
{
delete LC;
delete domain;
// remove all nodes again
for (PointSet::iterator iter = NodeList.begin();
!NodeList.empty();
iter = NodeList.begin()) {
delete *iter;
NodeList.erase(iter);
}
// delete in correct order
World::purgeInstance();
WorldTime::purgeInstance();
}
/** UnitTest for correct construction
*/
void LinkedCell_ModelTest::AllocationTest()
{
// check that first cell is allocated
LinkedCell::tripleIndex index;
index[0] = index[1] = index[2] = 0;
CPPUNIT_ASSERT(LC->N->getN()(index) != NULL);
// check that very last cell is allocated
index[0] = index[1] = index[2] = (size_t)floor(NUMBERCELLS)-1;
CPPUNIT_ASSERT(LC->N->getN()(index) != NULL);
}
/** UnitTest for getSize()
*/
void LinkedCell_ModelTest::getSizeTest()
{
// check getSize()
for(size_t i=0; igetSize(i));
#ifndef NDEBUG
std::cout << "The following assertion is intended and is not a failure of the code." << std::endl;
CPPUNIT_ASSERT_THROW( LC->getSize(4), Assert::AssertionFailure);
#endif
}
/** UnitTest for Reset()
*/
void LinkedCell_ModelTest::ResetTest()
{
LC->Reset();
for(size_t i=0; igetSize(i));
}
/** UnitTest for insertPointCloud()
*/
void LinkedCell_ModelTest::insertPointCloudTest()
{
// create the linked cell structure
PointCloudAdaptor< PointSet > cloud(&NodeList, std::string("NodeList"));
LC->insertPointCloud(cloud);
// assure that we are updated before accessing internals
CPPUNIT_ASSERT_EQUAL( true, *(LC->N->UpToDate) );
// test structure
CPPUNIT_ASSERT_EQUAL(((size_t)floor(NUMBERCELLS)), LC->CellLookup.size());
LinkedCell::tripleIndex index;
for (size_t i=0;i<((size_t)floor(NUMBERCELLS));++i) {
index[0] = index[1] = index[2] = i;
// assert that in the destined cell we have one Walker
CPPUNIT_ASSERT_EQUAL((size_t)1, LC->N->getN()(index)->size());
}
index[0] = 9;
index[1] = index[2] = 0;
// assert that in the destined cell we have one Walker
CPPUNIT_ASSERT_EQUAL((size_t)0, LC->N->getN()(index)->size());
}
/** UnitTest for setPartition()
*/
void LinkedCell_ModelTest::setPartitionTest()
{
RealSpaceMatrix Pmatrix = LC->Partition;
RealSpaceMatrix Dmatrix = LC->Dimensions;
LC->Reset();
LC->setPartition(2.*EDGELENGTH);
Pmatrix *= 0.5;
Dmatrix *= 0.5;
CPPUNIT_ASSERT_EQUAL(Pmatrix, LC->Partition);
CPPUNIT_ASSERT_EQUAL(Dmatrix, LC->Dimensions);
}
/** UnitTest for getStep()
*/
void LinkedCell_ModelTest::getStepTest()
{
// zero distance
LinkedCell::tripleIndex index = LC->getStep(0.);
for (size_t i = 0; igetStep(length);
for (size_t i = 0; igetStep(length);
for (size_t i = 0; igetIndexToVector(test);
for (size_t i = 0; igetIndexToVector(test);
for (size_t i = 0; igetIndexToVector(test);
for (size_t i = 0; isetName(std::string("Walker9"));
Walker->setPosition(Vector(9.8,7.6,5.4));
PointCloudAdaptor< PointSet > cloud(&NodeList, std::string("NodeList"));
LC->insertPointCloud(cloud);
// check addNode
{
LC->addNode(Walker);
// assure that we are updated before accessing internals
CPPUNIT_ASSERT_EQUAL( true, *(LC->N->UpToDate) );
CPPUNIT_ASSERT_EQUAL( NodeList.size()+1, LC->CellLookup.size());
LinkedCell::tripleIndex index1 = LC->getIndexToVector(Walker->getPosition());
const LinkedCell::tripleIndex &index2 = LC->CellLookup[Walker]->getIndices();
CPPUNIT_ASSERT(index1 == index2);
}
// check moveNode
{
LinkedCell::tripleIndex index1 = LC->getIndexToVector(Walker->getPosition());
const LinkedCell::tripleIndex &index2 = LC->CellLookup[Walker]->getIndices();
Walker->setPosition(Vector(0.,0.,0.));
LinkedCell::tripleIndex newindex1 = LC->getIndexToVector(Walker->getPosition());
CPPUNIT_ASSERT( index1 != newindex1);
// we have to call moveNode ourselves, as we have just added TesselPoints, not via World
LC->moveNode(Walker);
// assure that we are updated before accessing internals
CPPUNIT_ASSERT_EQUAL( true, *(LC->N->UpToDate) );
const LinkedCell::tripleIndex &newindex2 = LC->CellLookup[Walker]->getIndices();
CPPUNIT_ASSERT( index2 != newindex2);
}
// check deleteNode
{
LC->deleteNode(Walker);
// assure that we are updated before accessing internals
CPPUNIT_ASSERT_EQUAL( true, *(LC->N->UpToDate) );
CPPUNIT_ASSERT_EQUAL( NodeList.size(), LC->CellLookup.size());
}
delete Walker;
}
/** UnitTest whether lazy updates are working.
*/
void LinkedCell_ModelTest::lazyUpdatesTest()
{
// create point
TesselPoint * Walker = new TesselPoint();
Walker->setName(std::string("Walker9"));
Walker->setPosition(Vector(9.8,7.6,5.4));
TesselPoint * Walker2 = new TesselPoint();
Walker2->setName(std::string("Walker10"));
Walker2->setPosition(Vector(9.8,7.6,5.4));
PointCloudAdaptor< PointSet > cloud(&NodeList, std::string("NodeList"));
LC->insertPointCloud(cloud);
// initial read operation
{
CPPUNIT_ASSERT( !NodeList.empty() );
LinkedCell::tripleIndex index = LC->getIndexToVector((*NodeList.begin())->getPosition());
const size_t size = LC->N->getN()(index)->size(); // this will cause the update
CPPUNIT_ASSERT( size >= (size_t)1 );
}
// do some write ops
LC->addNode(Walker);
LC->addNode(Walker2);
CPPUNIT_ASSERT( LC->Changes->queue.find(Walker) != LC->Changes->queue.end() );
LinkedCell::LinkedCell_Model::Update *update = LC->Changes->queue[Walker];
Walker->setPosition(Vector(0.,0.,0.));
LC->moveNode(Walker);
// check that they all reside in cache and nothing is changed so far
CPPUNIT_ASSERT( LC->Changes->queue.size() > (size_t)0 );
// check that add priority is prefered over move
CPPUNIT_ASSERT( LC->Changes->queue[Walker] == update );
// perform read op
{
LinkedCell::tripleIndex index = LC->getIndexToVector(Walker->getPosition());
CPPUNIT_ASSERT( LC->N->getN()(index)->size() >= (size_t)1 );
}
// check that cache is emptied
CPPUNIT_ASSERT_EQUAL( LC->Changes->queue.size(), (size_t)0 );
delete Walker;
delete Walker2;
}