Commit b17ca5ca authored by Christoph Schwarzmeier's avatar Christoph Schwarzmeier
Browse files

Merge branch 'check_interaction_radius' into 'master'

added asserts to ensure interactionRadius is set properly

See merge request walberla/walberla!439
parents 84a3bf81 319a6ae2
......@@ -769,6 +769,7 @@ int main( int argc, char **argv )
{
mesa_pd::data::Particle&& p = *ps->create(true);
p.setPosition(halfSpacePosition);
p.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p.setOwner(mpi::MPIManager::instance()->rank());
p.setShapeID(halfSpaceShape);
mesa_pd::data::particle_flags::set(p.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE);
......
......@@ -281,6 +281,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
// create bounding planes
mesa_pd::data::Particle p0 = *ps->create(true);
p0.setPosition(simulationDomain.minCorner());
p0.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p0.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,0,1) ));
p0.setOwner(mpi::MPIManager::instance()->rank());
p0.setType(0);
......@@ -289,6 +290,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
mesa_pd::data::Particle p1 = *ps->create(true);
p1.setPosition(simulationDomain.maxCorner());
p1.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p1.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,0,-1) ));
p1.setOwner(mpi::MPIManager::instance()->rank());
p1.setType(0);
......@@ -297,6 +299,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
mesa_pd::data::Particle p2 = *ps->create(true);
p2.setPosition(simulationDomain.minCorner());
p2.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p2.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(1,0,0) ));
p2.setOwner(mpi::MPIManager::instance()->rank());
p2.setType(0);
......@@ -305,6 +308,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
mesa_pd::data::Particle p3 = *ps->create(true);
p3.setPosition(simulationDomain.maxCorner());
p3.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p3.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(-1,0,0) ));
p3.setOwner(mpi::MPIManager::instance()->rank());
p3.setType(0);
......@@ -313,6 +317,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
mesa_pd::data::Particle p4 = *ps->create(true);
p4.setPosition(simulationDomain.minCorner());
p4.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p4.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,1,0) ));
p4.setOwner(mpi::MPIManager::instance()->rank());
p4.setType(0);
......@@ -321,6 +326,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con
mesa_pd::data::Particle p5 = *ps->create(true);
p5.setPosition(simulationDomain.maxCorner());
p5.setInteractionRadius(std::numeric_limits<real_t>::infinity());
p5.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,-1,0) ));
p5.setOwner(mpi::MPIManager::instance()->rank());
p5.setType(0);
......
......@@ -147,24 +147,28 @@ int main( int argc, char **argv )
mesa_pd::data::Particle&& p1 = *ps->create();
p1.setPosition(position1);
p1.setInteractionRadius(sphereRadius);
p1.setShapeID(sphereShape);
p1.setLinearVelocity(Vector3<real_t>(relativeVelocity,-relativeVelocity,real_t(0.5)*relativeVelocity));
auto idxSph1 = p1.getIdx();
mesa_pd::data::Particle&& p2 = *ps->create();
p2.setPosition(position2);
p2.setInteractionRadius(sphereRadius);
p2.setShapeID(sphereShape);
p2.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(2),real_t(0)));
auto idxSph2 = p2.getIdx();
mesa_pd::data::Particle&& p3 = *ps->create();
p3.setPosition(position3);
p3.setInteractionRadius(sphereRadius);
p3.setShapeID(sphereShape);
p3.setLinearVelocity(Vector3<real_t>(real_t(2),real_t(0),real_t(2)));
auto idxSph3 = p3.getIdx();
mesa_pd::data::Particle&& p4 = *ps->create();
p4.setPosition(position4);
p4.setInteractionRadius(sphereRadius);
p4.setShapeID(sphereShape);
p4.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),real_t(-0.5)*relativeVelocity));
auto idxSph4 = p4.getIdx();
......@@ -228,24 +232,28 @@ int main( int argc, char **argv )
mesa_pd::data::Particle&& p1 = *ps->create();
p1.setPosition(position1);
p1.setInteractionRadius(sphereRadius);
p1.setShapeID(sphereShape);
p1.setLinearVelocity(Vector3<real_t>(relativeVelocity,-relativeVelocity,real_t(0.5)*relativeVelocity));
auto idxSph1 = p1.getIdx();
mesa_pd::data::Particle&& p2 = *ps->create();
p2.setPosition(position2);
p2.setInteractionRadius(sphereRadius);
p2.setShapeID(sphereShape);
p2.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(2),real_t(0)));
auto idxSph2 = p2.getIdx();
mesa_pd::data::Particle&& p3 = *ps->create();
p3.setPosition(position3);
p3.setInteractionRadius(sphereRadius);
p3.setShapeID(sphereShape);
p3.setLinearVelocity(Vector3<real_t>(real_t(2),real_t(0),real_t(2)));
auto idxSph3 = p3.getIdx();
mesa_pd::data::Particle&& p4 = *ps->create();
p4.setPosition(position4);
p4.setInteractionRadius(sphereRadius);
p4.setShapeID(sphereShape);
p4.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),real_t(-0.5)*relativeVelocity));
auto idxSph4 = p4.getIdx();
......@@ -328,6 +336,7 @@ int main( int argc, char **argv )
mesa_pd::data::Particle&& p1 = *ps->create();
p1.setPosition(position1);
p1.setInteractionRadius(sphereRadius);
p1.setShapeID(sphereShape);
p1.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),relativeVelocity));
auto idxSph1 = p1.getIdx();
......@@ -335,29 +344,34 @@ int main( int argc, char **argv )
// mix up order to test Sph - HSp and HSp - Sph variants
mesa_pd::data::Particle&& pW = *ps->create(true);
pW.setPosition(wallPosition);
pW.setInteractionRadius(std::numeric_limits<real_t>::infinity());
pW.setShapeID(planeShape);
auto idxWall = pW.getIdx();
mesa_pd::data::Particle&& p2 = *ps->create();
p2.setPosition(position2);
p2.setInteractionRadius(sphereRadius);
p2.setShapeID(sphereShape);
p2.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),-relativeVelocity));
auto idxSph2 = p2.getIdx();
mesa_pd::data::Particle&& p3 = *ps->create();
p3.setPosition(position3);
p3.setInteractionRadius(sphereRadius);
p3.setShapeID(sphereShape);
p3.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),relativeVelocity));
auto idxSph3 = p3.getIdx();
mesa_pd::data::Particle&& p4 = *ps->create();
p4.setPosition(position4);
p4.setInteractionRadius(sphereRadius);
p4.setShapeID(sphereShape);
p4.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),relativeVelocity));
auto idxSph4 = p4.getIdx();
mesa_pd::data::Particle&& p5 = *ps->create();
p5.setPosition(position5);
p5.setInteractionRadius(sphereRadius);
p5.setShapeID(sphereShape);
p5.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),relativeVelocity));
auto idxSph5 = p5.getIdx();
......
......@@ -15,13 +15,11 @@
//
//! \file
//! \author Sebastian Eibl <sebastian.eibl@fau.de>
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#include <mesa_pd/vtk/ParticleVtkOutput.h>
#include <mesa_pd/collision_detection/AnalyticContactDetection.h>
#include <mesa_pd/collision_detection/GeneralContactDetection.h>
#include <mesa_pd/data/LinkedCells.h>
#include <mesa_pd/data/ParticleAccessor.h>
#include <mesa_pd/data/ParticleStorage.h>
......@@ -31,10 +29,8 @@
#include <mesa_pd/kernel/InsertParticleIntoLinkedCells.h>
#include <mesa_pd/kernel/ParticleSelector.h>
#include <mesa_pd/mpi/ContactFilter.h>
#include <mesa_pd/mpi/notifications/ForceTorqueNotification.h>
#include <mesa_pd/mpi/SyncNextNeighbors.h>
#include <blockforest/BlockForest.h>
#include <blockforest/Initialization.h>
#include <core/Abort.h>
#include <core/Environment.h>
......@@ -42,9 +38,7 @@
#include <core/mpi/Reduce.h>
#include <core/grid_generator/SCIterator.h>
#include <core/logging/Logging.h>
#include <core/waLBerlaBuildInfo.h>
#include <functional>
#include <memory>
#include <string>
......@@ -68,7 +62,13 @@ private:
std::shared_ptr<data::ShapeStorage> ss_;
};
int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
/*
* Tests linked cells
* Fully periodic, simple cubic sphere array is created
* Together with linked cells of size 2 * sphere spacing.
* This allows to analytically calculate how many particles should reside in each linked cell and how many contacts should be found and treated.
*/
int main( const int particlesPerAxisPerProcess = 2 )
{
using namespace walberla::timing;
......@@ -80,15 +80,18 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
math::seedRandomGenerator( static_cast<unsigned int>(1337 * walberla::mpi::MPIManager::instance()->worldRank()) );
const real_t spacing(1.0);
const real_t radius = real_t(0.9);
const real_t generationSpacing = 1_r;
const int linkedCellMultipleOfGenerationSpacing = 2;
WALBERLA_CHECK_EQUAL(particlesPerAxisPerProcess % linkedCellMultipleOfGenerationSpacing, 0, "Only a multiple of " << linkedCellMultipleOfGenerationSpacing << " is allowed");
WALBERLA_LOG_INFO_ON_ROOT("*** BLOCKFOREST ***");
const int centerParticles = particlesPerAxis * particlesPerAxis * particlesPerAxis;
const int faceParticles = particlesPerAxis * particlesPerAxis * 6;
const int edgeParticles = particlesPerAxis * 4 * 3;
const int centerParticles = particlesPerAxisPerProcess * particlesPerAxisPerProcess * particlesPerAxisPerProcess;
const int faceParticles = particlesPerAxisPerProcess * particlesPerAxisPerProcess * 6;
const int edgeParticles = particlesPerAxisPerProcess * 4 * 3;
const int cornerParticles = 8;
WALBERLA_LOG_DEVEL_VAR_ON_ROOT(particlesPerAxis);
WALBERLA_LOG_DEVEL_VAR_ON_ROOT(particlesPerAxisPerProcess);
WALBERLA_LOG_DEVEL_VAR_ON_ROOT(centerParticles);
WALBERLA_LOG_DEVEL_VAR_ON_ROOT(faceParticles);
WALBERLA_LOG_DEVEL_VAR_ON_ROOT(edgeParticles);
......@@ -96,14 +99,16 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
// create forest
const real_t eps = real_c(0.01); //shift to make contact points unambigous
Vector3<uint_t>blocksPerDirection (2,2,2);
int numBlocks = int(blocksPerDirection[0] * blocksPerDirection[1] * blocksPerDirection[2]);
Vector3<bool> periodicity(true, true, true);
auto forest = blockforest::createBlockForest( math::AABB(real_t(0),
real_t(0),
real_t(0),
real_c(particlesPerAxis) * real_t(2),
real_c(particlesPerAxis) * real_t(2),
real_c(particlesPerAxis) * real_t(2)).getTranslated(Vec3(eps,eps,eps)),
Vector3<uint_t>(2,2,2),
Vector3<bool>(true, true, true) );
real_c(particlesPerAxisPerProcess) * generationSpacing * real_c(blocksPerDirection[0]),
real_c(particlesPerAxisPerProcess) * generationSpacing * real_c(blocksPerDirection[1]),
real_c(particlesPerAxisPerProcess) * generationSpacing * real_c(blocksPerDirection[2])).getTranslated(Vec3(eps,eps,eps)),
blocksPerDirection, periodicity);
domain::BlockForestDomain domain(forest);
auto localDomain = forest->begin()->getAABB();
......@@ -115,13 +120,14 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
auto ps = std::make_shared<data::ParticleStorage>(100);
auto ss = std::make_shared<data::ShapeStorage>();
ParticleAccessorWithShape accessor(ps, ss);
data::LinkedCells lc(localDomain.getExtended(spacing), spacing );
const real_t linkedCellSize = real_c(linkedCellMultipleOfGenerationSpacing) * generationSpacing;
data::LinkedCells lc(localDomain.getExtended(linkedCellSize), linkedCellSize );
auto smallSphere = ss->create<data::Sphere>( radius );
ss->shapes[smallSphere]->updateMassAndInertia(real_t(2707));
for (auto& iBlk : *forest)
{
for (auto pt : grid_generator::SCGrid(iBlk.getAABB(), Vector3<real_t>(spacing, spacing, spacing) * real_c(0.5), spacing))
for (auto pt : grid_generator::SCGrid(iBlk.getAABB(), Vector3<real_t>(generationSpacing, generationSpacing, generationSpacing) * real_c(0.5), generationSpacing))
{
WALBERLA_CHECK(iBlk.getAABB().contains(pt));
......@@ -133,7 +139,7 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
}
}
int64_t numParticles = int64_c(ps->size());
walberla::mpi::reduceInplace(numParticles, walberla::mpi::SUM);
walberla::mpi::allReduceInplace(numParticles, walberla::mpi::SUM);
WALBERLA_LOG_INFO_ON_ROOT("#particles created: " << numParticles);
WALBERLA_LOG_INFO_ON_ROOT("*** SETUP - END ***");
......@@ -146,14 +152,32 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
// initial sync
WALBERLA_CHECK_EQUAL(ps->size(), centerParticles);
SNN(*ps, domain);
WALBERLA_CHECK_EQUAL(ps->size(), centerParticles + faceParticles + edgeParticles + cornerParticles);
int numKnownParticles = centerParticles + faceParticles + edgeParticles + cornerParticles;
WALBERLA_CHECK_EQUAL(ps->size(), numKnownParticles);
lc.clear();
ps->forEachParticle(true, kernel::SelectAll(), accessor, ipilc, accessor, lc);
WALBERLA_CHECK_EQUAL(lc.cells_.size(), centerParticles + faceParticles + edgeParticles + cornerParticles);
int cell0 = 0;
int cell1 = 0;
int interiorCellsPerDirection = particlesPerAxisPerProcess / linkedCellMultipleOfGenerationSpacing;
int numLinkedCellsPerProcess = (interiorCellsPerDirection+2) * (interiorCellsPerDirection+2) * (interiorCellsPerDirection+2);
WALBERLA_CHECK_EQUAL(lc.cells_.size(), numLinkedCellsPerProcess);
const int numLinkedCellsCenter = interiorCellsPerDirection * interiorCellsPerDirection * interiorCellsPerDirection;
const int numLinkedCellsFace = interiorCellsPerDirection * interiorCellsPerDirection * 6;
const int numLinkedCellsEdge = interiorCellsPerDirection * 12;
const int numLinkedCellsCorner = 8;
const int numParticlesPerCenterCell = centerParticles / numLinkedCellsCenter;
const int numParticlesPerFaceCell = faceParticles / numLinkedCellsFace;
const int numParticlesPerEdgeCell = edgeParticles / numLinkedCellsEdge;
const int numParticlesPerCornerCell = cornerParticles / numLinkedCellsCorner;
int cellsCenter = 0;
int cellsFace = 0;
int cellsEdge = 0;
int cellsCorner = 0;
for (const auto& idx : lc.cells_)
{
int particleCounter = 0;
......@@ -163,18 +187,18 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
++particleCounter;
p_idx = ps->getNextParticle(uint_c(p_idx));
}
if (particleCounter==0)
{
++cell0;
} else if (particleCounter==1)
{
++cell1;
} else {
WALBERLA_CHECK(false);
}
if (particleCounter == numParticlesPerCenterCell) ++cellsCenter;
else if (particleCounter == numParticlesPerFaceCell) ++cellsFace;
else if (particleCounter == numParticlesPerEdgeCell) ++cellsEdge;
else if (particleCounter == numParticlesPerCornerCell) ++cellsCorner;
else WALBERLA_CHECK(false, "Linked cell found with unexpected number of particles " << particleCounter);
}
WALBERLA_CHECK_EQUAL(cell0, 0);
WALBERLA_CHECK_EQUAL(cell1, centerParticles + faceParticles + edgeParticles + cornerParticles); //ghost particles only at face, no ghost particle at edges and corners
WALBERLA_CHECK_EQUAL(cellsCenter, numLinkedCellsCenter);
WALBERLA_CHECK_EQUAL(cellsFace, numLinkedCellsFace);
WALBERLA_CHECK_EQUAL(cellsEdge, numLinkedCellsEdge);
WALBERLA_CHECK_EQUAL(cellsCorner, numLinkedCellsCorner);
std::atomic<int64_t> contactsChecked (0);
std::atomic<int64_t> contactsDetected(0);
......@@ -201,9 +225,10 @@ int main( const int particlesPerAxis = 2, const real_t radius = real_t(0.9) )
WALBERLA_LOG_DEVEL_ON_ROOT( "contacts checked/detected/treated: " << contactsChecked << " / " << contactsDetected << " / " << contactsTreated );
WALBERLA_CHECK_EQUAL(contactsChecked, (centerParticles*26 + faceParticles*17 + edgeParticles*11 + cornerParticles*7) / 2 );
WALBERLA_CHECK_LESS_EQUAL(contactsChecked, numKnownParticles * numKnownParticles / 2 ); // has to be better than n^2 checking
WALBERLA_CHECK_EQUAL(contactsDetected, (centerParticles*26 + faceParticles*17 + edgeParticles*11 + cornerParticles*7) / 2 );
//TODO: ContactsTreated
const int totalNumberPairWiseContactsInDomain = 26 * int(numParticles) / 2; //fully-periodic simple cubic grid
WALBERLA_CHECK_EQUAL(contactsTreated, totalNumberPairWiseContactsInDomain / numBlocks);
return EXIT_SUCCESS;
}
......@@ -216,8 +241,6 @@ int main( int argc, char* argv[] )
walberla::Environment env(argc, argv);
WALBERLA_UNUSED(env);
walberla::mesa_pd::main( 2 );
walberla::mesa_pd::main( 3 );
walberla::mesa_pd::main( 4 );
walberla::mesa_pd::main( 5 );
return EXIT_SUCCESS;
}
......@@ -79,7 +79,7 @@ int main( int argc, char ** argv )
auto ps = std::make_shared<data::ParticleStorage>(100);
auto ss = std::make_shared<data::ShapeStorage>();
ParticleAccessorWithShape accessor(ps, ss);
data::LinkedCells lc(math::AABB(-1,-1,-1,4,4,4), real_t(1));
data::LinkedCells lc(math::AABB(-1,-1,-1,4,4,4), real_t(1.3));
//initialize particles
const real_t radius = real_t(0.6);
......
......@@ -66,6 +66,7 @@ int main( int argc, char ** argv )
{
data::Particle&& p = *storage->create();
p.getPositionRef() = (*it);
p.setInteractionRadius(0.1_r);
p.setShapeID(smallSphere);
}
......
......@@ -100,7 +100,7 @@ int main( int argc, char ** argv )
//init data structures
auto ps = std::make_shared<data::ParticleStorage>(100);
auto ss = std::make_shared<data::ShapeStorage>();
data::LinkedCells lc(blk.getAABB(), real_t(1));
data::LinkedCells lc(blk.getAABB(), real_t(1.1));
std::vector<collision_detection::AnalyticContactDetection> cs1(100);
std::vector<collision_detection::AnalyticContactDetection> cs2(100);
......
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