diff --git a/src/pe/basic.h b/src/pe/basic.h index 08051705953cf2e5641188942c29a11e0c0cf7ec..c56163c5d13cf5979f32bf51f7202b43a6995533 100644 --- a/src/pe/basic.h +++ b/src/pe/basic.h @@ -51,3 +51,5 @@ #include "pe/utility/CreateWorld.h" #include "pe/utility/GetBody.h" + +#include "pe/world/World.h" diff --git a/src/pe/world/World.cpp b/src/pe/world/World.cpp new file mode 100644 index 0000000000000000000000000000000000000000..002d3dfd13c3857f6464952dcfb23933c43eacff --- /dev/null +++ b/src/pe/world/World.cpp @@ -0,0 +1,123 @@ +#include "World.h" + +#include "pe/cr/HCSITS.h" + +namespace walberla +{ +namespace pe +{ + + + +World::World(shared_ptr<BlockForest> forest, shared_ptr<BodyStorage> globalBodyStorage, + BlockDataID storageID, BlockDataID ccdID, BlockDataID fcdID, boost::function<void(void)> syncCall, + boost::function<void(void)> syncCallWithoutTT, Config::BlockHandle peConfig, shared_ptr<WcTimingTree> timingTree) : + blockForest_(forest), globalBodyStorage_(globalBodyStorage), timingTree_(timingTree), storageID_(storageID), ccdID_(ccdID), fcdID_(fcdID), syncCall_(syncCall), syncCallWithoutTT_(syncCallWithoutTT) +{ + + shortestDistanceInBlock_ = 0; + longestDistanceFromParticleCenterToEdge_ = 0; + + real_t blockXSize = forest->getRootBlockXSize(); + real_t blockYSize = forest->getRootBlockYSize(); + real_t blockZSize = forest->getRootBlockZSize(); + + if (blockXSize <= blockYSize && blockXSize <= blockZSize) + { + shortestDistanceInBlock_ = blockXSize; + } + else if (blockYSize <= blockZSize) + { + shortestDistanceInBlock_ = blockYSize; + } + else + { + shortestDistanceInBlock_ = blockZSize; + } + + serializeFilename_ = peConfig.getParameter<std::string>("SuspendFilename", ""); + + std::string collisionResolverString = peConfig.getParameter<std::string>("CollisionResolver", "DEM"); + + Config::BlockHandle collisionConf = peConfig.getBlock("CollisonResolverConfig"); + + if (collisionResolverString == "DEM") + { + shared_ptr<cr::DEM> cr = make_shared<cr::DEM>(globalBodyStorage_, forest, storageID_, ccdID_, fcdID_, timingTree_.get()); + collisionResolver_ = cr; + } + else if (collisionResolverString == "HCSITS") + { + shared_ptr<cr::HCSITS> cr = make_shared<cr::HCSITS>(globalBodyStorage_, forest, storageID_, ccdID_, fcdID_, timingTree_.get()); + configure(collisionConf, *cr); + collisionResolver_ = cr; + } + else + { + WALBERLA_ABORT("Solver not implemented in World" << collisionResolverString); + } + + Vec3 globalLinearAcceleration = peConfig.getParameter<Vec3>("globalLinearAcceleration", Vec3(0, 0, 0)); + WALBERLA_LOG_INFO_ON_ROOT("globalLinearAcceleration: " << globalLinearAcceleration); + collisionResolver_->setGlobalLinearAcceleration(globalLinearAcceleration); +} + + +void World::syncAfterParticleCreation() +{ + mpi::allReduceInplace(longestDistanceFromParticleCenterToEdge_, mpi::MAX); + uint_t maximumNumberOfSpannedBlocks = uint_c(ceil(longestDistanceFromParticleCenterToEdge_ / shortestDistanceInBlock_)); + if (maximumNumberOfSpannedBlocks < 1) + { + maximumNumberOfSpannedBlocks = 1; + } + for (uint_t i = 0; i < maximumNumberOfSpannedBlocks; ++i) + { + syncCallWithoutTT_(); + } +} + + +PlaneID World::createPlane(id_t uid, Vec3 normal, const Vec3 &gpos, MaterialID material) +{ + return pe::createPlane(*globalBodyStorage_, uid, normal, gpos, material); +} + + +SphereID World::createSphere(id_t uid, const Vec3 &gpos, real_t radius, MaterialID material, bool global, bool communicating, bool infiniteMass) +{ + if (radius > longestDistanceFromParticleCenterToEdge_) + { + longestDistanceFromParticleCenterToEdge_ = radius; + } + return pe::createSphere(*globalBodyStorage_, *blockForest_, storageID_, uid, gpos, radius, material, global, communicating, infiniteMass); +} + + +BoxID World::createBox(id_t uid, const Vec3& gpos, const Vec3& lengths, MaterialID material, bool global, bool communicating, bool infiniteMass) +{ + for(uint_t i = 0; i < 3; i++) { + if ((lengths[i]/2.0) > longestDistanceFromParticleCenterToEdge_) + { + longestDistanceFromParticleCenterToEdge_ = real_c(lengths[i]/2.0); + } + } + + return pe::createBox(*globalBodyStorage_, *blockForest_, storageID_, uid, gpos, lengths, material, global, communicating, infiniteMass); +} + +CapsuleID World::createCapsule(id_t uid, const Vec3& gpos, const real_t radius, const real_t length, MaterialID material, bool global, bool communicating, bool infiniteMass) +{ + + if((length/2.0 + radius) > longestDistanceFromParticleCenterToEdge_) + { + longestDistanceFromParticleCenterToEdge_ = real_c(length/2.0 + radius); + } + return pe::createCapsule(*globalBodyStorage_, *blockForest_, storageID_, uid, gpos, radius, length, material, global, communicating, infiniteMass); +} + + + + +} // namespace pe +} // namespace walberla diff --git a/src/pe/world/World.h b/src/pe/world/World.h new file mode 100644 index 0000000000000000000000000000000000000000..e8914accaeb2602259056c64b30db863c4d6ae9c --- /dev/null +++ b/src/pe/world/World.h @@ -0,0 +1,142 @@ +#pragma once + +#include "blockforest/BlockForest.h" +#include "core/DataTypes.h" +#include "core/config/Config.h" +#include "domain_decomposition/BlockDataID.h" +#include "pe/basic.h" + +#include <fstream> + +namespace walberla +{ +namespace pe +{ + +class World +{ +public: + World(shared_ptr<BlockForest> forest, shared_ptr<BodyStorage> globalBodyStorage, + BlockDataID storageID, BlockDataID ccdID, BlockDataID fcdID, boost::function<void(void)> syncCall, + boost::function<void(void)> syncCallWithoutTT, Config::BlockHandle peConfig, shared_ptr<WcTimingTree> timingTree = nullptr); + + void syncAfterParticleCreation(); + void sync() { syncCall_(); } + void timestep(const real_t dt = 1) { collisionResolver_->timestep(dt); } + void simulationStep(const real_t dt = 1) + { + timestep(dt); + sync(); + } + + void serialize() { + if(serializeFilename_ == "") return; + blockForest_->saveBlockData(serializeFilename_, storageID_); + }; + + void serialize(std::string filename) { + if(filename == "") return; + blockForest_->saveBlockData(filename, storageID_); + } + + const BlockDataID &getStorageID() const { return storageID_; } + const BlockDataID &getFCDID() const { return fcdID_; } + shared_ptr<cr::ICR> getCollisionResolver() { return collisionResolver_; } + const Vec3 &getGlobalLinearAcceleration() const { return collisionResolver_->getGlobalLinearAcceleration(); }; + void setGlobalLinearAcceleration(const Vec3 &newAcceleration) { collisionResolver_->setGlobalLinearAcceleration(newAcceleration); }; + + PlaneID createPlane(id_t uid, Vec3 normal, const Vec3 &gpos, MaterialID material = Material::find("iron")); + SphereID createSphere(id_t uid, const Vec3 &gpos, real_t radius, MaterialID material = Material::find("iron"), bool global = false, bool communicating = true, bool infiniteMass = false); + BoxID createBox(id_t uid, const Vec3& gpos, const Vec3& lengths, MaterialID material = Material::find("iron"), bool global = false, bool communicating = true, bool infiniteMass = false); + CapsuleID createCapsule(id_t uid, const Vec3& gpos, const real_t radius, const real_t length, MaterialID material = Material::find("iron"), bool global = false, bool communicating = true, bool infiniteMass = false); + + template<typename functionType, typename... Rest> + BodyID createBody(functionType creationFunction, const real_t long_axis_length, Rest... args) { + if(long_axis_length/2 > longestDistanceFromParticleCenterToEdge_) { + longestDistanceFromParticleCenterToEdge_ = long_axis_length/2; + } + + return creationFunction(*globalBodyStorage_, *blockForest_, storageID_, args...); + } + + +private: + const shared_ptr<BlockForest> blockForest_; + const shared_ptr<BodyStorage> globalBodyStorage_; + const shared_ptr<WcTimingTree> timingTree_; + + const BlockDataID storageID_; + const BlockDataID ccdID_; + const BlockDataID fcdID_; + + shared_ptr<cr::ICR> collisionResolver_; + + real_t shortestDistanceInBlock_; + real_t longestDistanceFromParticleCenterToEdge_; + + std::string serializeFilename_; + + const boost::function<void(void)> syncCall_; + const boost::function<void(void)> syncCallWithoutTT_; +}; + +template <typename BodyTuple> +World createWorldFromConfig(shared_ptr<BlockForest> forest, Config::BlockHandle peConf, shared_ptr<WcTimingTree> timingTree) { + + SetBodyTypeIDs<BodyTuple>::execute(); + + auto globalBodyStorage = make_shared<BodyStorage>(); + + std::string resumeString = peConf.getParameter<std::string>("ResumeFilename", ""); + + BlockDataID storageID; + + // Support suspend resume + if(resumeString != "") { + std::ifstream f(resumeString.c_str()); + if(f.good()) { + f.close(); + storageID = forest->loadBlockData(resumeString.c_str(), createStorageDataHandling<BodyTuple>()); + } + else { + f.close(); + storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + } + } + else { + storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + } + + //auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + auto fcdID = forest->addBlockData(fcd::createSimpleFCDDataHandling<BodyTuple>(), "FCD"); + + for (auto blockIt = forest->begin(); blockIt != forest->end(); ++blockIt) { ccd::ICCD* ccd = blockIt->getData< ccd::ICCD >( ccdID ); ccd->reloadBodies(); } + + boost::function<void(void)> syncCall; + boost::function<void(void)> syncCallWithoutTT; + + bool largeParticleSupport = peConf.getParameter<bool>("LargeParticleSupport", false); + if (!largeParticleSupport) + { + syncCall = boost::bind(pe::syncNextNeighbors<BodyTuple>, boost::ref(*forest), storageID, timingTree.get(), real_c(0.0), false); + } + else + { + syncCall = boost::bind(pe::syncShadowOwners<BodyTuple>, boost::ref(*forest), storageID, timingTree.get(), real_c(0.0), false); + } + + if (!largeParticleSupport) + { + syncCallWithoutTT = boost::bind(pe::syncNextNeighbors<BodyTuple>, boost::ref(*forest), storageID, static_cast<WcTimingTree *>(NULL), real_c(0.0), false); + } + else + { + syncCallWithoutTT = boost::bind(pe::syncShadowOwners<BodyTuple>, boost::ref(*forest), storageID, static_cast<WcTimingTree *>(NULL), real_c(0.0), false); + } + + return World(forest, globalBodyStorage, storageID, ccdID, fcdID, syncCall, syncCallWithoutTT, peConf, timingTree); +} + +} // namespace pe +} // namespace walberla