diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index 7d5901c16064c4d3b103d5af59b40db3d9aa6403..f9c1d6e7a8feeb0d4bfbb6a1e55ab2946c2b8cee 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory( AdaptiveMeshRefinementFluidParticleCoupling ) +add_subdirectory( CNT ) add_subdirectory( ComplexGeometry ) add_subdirectory( DEM ) add_subdirectory( MeshDistance ) diff --git a/apps/benchmarks/CNT/01_cnt_film.cpp b/apps/benchmarks/CNT/01_cnt_film.cpp new file mode 100644 index 0000000000000000000000000000000000000000..547d6f4c56214843fe29d402bace0d92075cb9fd --- /dev/null +++ b/apps/benchmarks/CNT/01_cnt_film.cpp @@ -0,0 +1,376 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "Config.h" +#include "InitializeCNTs.h" +#include "SphericalSegmentAccessor.h" +#include "SQLProperties.h" +#include "Statistics.h" +#include "TerminalColors.h" + +#include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/data/Flags.h" +#include "mesa_pd/data/LinkedCells.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/SparseLinkedCells.h" +#include <mesa_pd/kernel/AssocToBlock.h> +#include "mesa_pd/kernel/InsertParticleIntoLinkedCells.h" +#include "mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/cnt/AnisotropicVDWContact.h" +#include "mesa_pd/kernel/cnt/VBondContact.h" +#include "mesa_pd/kernel/cnt/ViscousDamping.h" +#include "mesa_pd/kernel/cnt/Parameters.h" +#include "mesa_pd/kernel/PFCDamping.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/mpi/ContactFilter.h" +#include "mesa_pd/mpi/notifications/ForceTorqueNotification.h" +#include "mesa_pd/mpi/ReduceProperty.h" +#include "mesa_pd/mpi/SyncNextNeighbors.h" +#include "mesa_pd/sorting/LinearizedCompareFunctor.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "blockforest/Initialization.h" +#include "core/Environment.h" +#include "core/math/Constants.h" +#include "core/timing/TimingPool.h" +#include "core/timing/TimingTree.h" +#include "sqlite/SQLite.h" +#include "vtk/VTKOutput.h" + +namespace walberla { +namespace mesa_pd { + +int main(int argc, char **argv) +{ + Environment env(argc, argv); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + logging::Logging::instance()->setStreamLogLevel(logging::Logging::INFO); + logging::Logging::instance()->setFileLogLevel(logging::Logging::INFO); + + WcTimingPool globalTP; + WcTimingPool loopTP; + WcTimingTree tt; + + WALBERLA_LOG_INFO_ON_ROOT("loading configuration parameters"); + globalTP["load config"].start(); + //---------------Generation of CNT configuration----------------------------- + FilmSpecimen filmSpecimen; // Data structure for CNT film + auto cfg = env.config(); + if (cfg == nullptr) + WALBERLA_ABORT("No config specified!"); + const Config::BlockHandle cntConf = cfg->getBlock("CNT"); + loadFromConfig(filmSpecimen, cntConf); + //=========================================================================== + globalTP["load config"].end(); + + WALBERLA_LOG_INFO_ON_ROOT("creating domain setup"); + globalTP["domain setup"].start(); + Vector3<bool> periodicity = Vector3<bool>(true, true, false); + if (filmSpecimen.oopp) periodicity[2] = true; + real_t maxZ = filmSpecimen.sizeZ; + real_t minZ = 0; + if (!filmSpecimen.oopp) + { + maxZ += real_c(filmSpecimen.numSegs) * filmSpecimen.spacing; + minZ -= real_c(filmSpecimen.numSegs) * filmSpecimen.spacing; + } + + auto forest = blockforest::createBlockForest( + AABB(0, 0, minZ, filmSpecimen.sizeX, filmSpecimen.sizeY, maxZ), // simulation domain + Vector3<uint_t>(filmSpecimen.numBlocksX, filmSpecimen.numBlocksY, filmSpecimen.numBlocksZ), // blocks in each direction + periodicity // periodicity + ); + if (!forest) WALBERLA_ABORT("No BlockForest created ... exiting!"); + + auto domain = std::make_shared<domain::BlockForestDomain> (forest); + + auto simulationDomain = forest->getDomain(); + WALBERLA_UNUSED(simulationDomain); + auto localDomain = forest->begin()->getAABB(); + for (auto& blk : *forest) + { + localDomain.merge(blk.getAABB()); + } + globalTP["domain setup"].end(); + + WALBERLA_LOG_INFO_ON_ROOT("creating initial particle setup"); + globalTP["generate CNT"].start(); + auto ps = std::make_shared<data::ParticleStorage>(10); + auto ac = SphericalSegmentAccessor(ps); + auto lc = data::SparseLinkedCells(localDomain.getExtended(4_r * kernel::cnt::outer_radius), 4_r * kernel::cnt::outer_radius ); + + int64_t numParticles = 0; + if (filmSpecimen.initialConfigurationFile.empty()) + { + numParticles = generateCNTs(filmSpecimen, ps, *domain); + } else + { + numParticles = loadCNTs(filmSpecimen.initialConfigurationFile, ps); + } + walberla::mpi::reduceInplace(numParticles, walberla::mpi::SUM); + WALBERLA_LOG_INFO_ON_ROOT("#particles created: " << numParticles); + globalTP["generate CNT"].end(); + + WALBERLA_LOG_INFO_ON_ROOT("setting up VTK output"); + auto vtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + vtkOutput->addOutput<data::SelectParticlePosition>("position"); + auto vtkWriter = walberla::vtk::createVTKOutput_PointData(vtkOutput, + "cnt", + 1, + filmSpecimen.vtkFolder, + "simulation_step", + true, + true, + true, + filmSpecimen.useMPIIO); + + WALBERLA_LOG_INFO_ON_ROOT("setting up interaction models"); + kernel::InsertParticleIntoSparseLinkedCells ipilc; + kernel::cnt::AnisotropicVDWContact anisotropicVdwContact; + kernel::cnt::VBondContact vBondContact; + kernel::cnt::ViscousDamping viscous_damping(filmSpecimen.viscousDamping * 1052.0_r, + filmSpecimen.viscousDamping * 1052.0_r); + kernel::PFCDamping pfcDamping(filmSpecimen.localDamping); + kernel::VelocityVerletPreForceUpdate vv_pre(kernel::cnt::dT); + kernel::VelocityVerletPostForceUpdate vv_post(kernel::cnt::dT); + mpi::ContactFilter contactFilter; + mpi::ReduceProperty RP; + mpi::SyncNextNeighbors SNN; + + WALBERLA_LOG_INFO_ON_ROOT("warmup"); + SNN(*ps, *domain); + sorting::LinearizedCompareFunctor linear(lc.domain_, Vector3<uint_t>(lc.numCellsPerDim_[0])); + ps->sort(linear); + vtkWriter->write(true); + + WALBERLA_LOG_INFO_ON_ROOT("running simulation"); + int64_t contactsChecked = 0; + int64_t contactsDetected = 0; + int64_t contactsTreated = 0; + + std::vector<Statistics> statistics; + + globalTP["sim loop"].start(); + for (auto i = 0; i < filmSpecimen.simulationSteps; ++i) + { + Statistics stats; + + loopTP["VV pre"].start(); + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_pre, + ac); + loopTP["VV pre"].end(); + + loopTP["SNN"].start(); + SNN(*ps, *domain); + loopTP["SNN"].end(); + + loopTP["GenerateSparseLinkedCells"].start(); + lc.clear(); + ps->forEachParticle(false, kernel::SelectAll(), ac, ipilc, ac, lc); + loopTP["GenerateSparseLinkedCells"].end(); + + loopTP["interaction"].start(); + contactsChecked = 0; + contactsDetected = 0; + contactsTreated = 0; + lc.forEachParticlePairHalf(false, + kernel::SelectAll(), + ac, + [&](size_t p_idx1, size_t p_idx2) + { + //ensure ordering + if (ac.getUid(p_idx1) > ac.getUid(p_idx2)) + std::swap(ac.getUidRef(p_idx1), ac.getUidRef(p_idx1)); + + ++contactsChecked; + auto dist = ac.getPosition(p_idx1) - ac.getPosition(p_idx2); + auto dist2 = math::dot(dist, dist); + auto cutoff = ac.getInteractionRadius(p_idx1) + ac.getInteractionRadius(p_idx2); + if (dist2 < cutoff * cutoff) + { + auto contactPoint = ac.getPosition(p_idx2) + 0.5_r * dist; + ++contactsDetected; + if (contactFilter(p_idx1, p_idx2, ac, contactPoint, *domain)) + { + ++contactsTreated; + constexpr bool period_X = false; + constexpr bool period_Y = false; + constexpr int max_segsX = 0; + constexpr int max_segsY = 0; + auto sameCluster = ac.getClusterID(p_idx2) == ac.getClusterID(p_idx1); + auto segmentDistance = std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)); + if ((sameCluster) && ((segmentDistance == 1) || + ((period_X) && (segmentDistance == max_segsX - 1)) || + ((period_Y) && (segmentDistance == max_segsY - 1)) + ) + ) + { + vBondContact(p_idx1, p_idx2, ac); + stats.bendingEnergy += vBondContact.getLastBendingEnergy(); + stats.shearEnergy += vBondContact.getLastShearEnergy(); + stats.tensileEnergy += vBondContact.getLastTensileEnergy(); + stats.twistingEnergy += vBondContact.getLastTwistingEnergy(); + stats.stretchEnergy += vBondContact.getLastBendingEnergy() + + vBondContact.getLastShearEnergy() + + vBondContact.getLastTensileEnergy() + + vBondContact.getLastTwistingEnergy(); + } + else if ((sameCluster) && (segmentDistance < 20)) + { + //do nothing + } else + { + anisotropicVdwContact(p_idx1, p_idx2, ac); + stats.vdwEnergy += anisotropicVdwContact.getLastEnergy(); + stats.numAlignedPairs += anisotropicVdwContact.isParallel() ? 1 : 0; + } + viscous_damping(p_idx1, p_idx2, ac); + } + } + }); + loopTP["interaction"].end(); + + loopTP["ReduceForce"].start(); + RP.operator()<ForceTorqueNotification>(*ps); + loopTP["ReduceForce"].end(); + + loopTP["PFDDamping"].start(); + ps->forEachParticle(false, kernel::SelectAll(), ac, pfcDamping, ac); + loopTP["PFDDamping"].end(); + + loopTP["VV post"].start(); + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_post, + ac); + loopTP["VV post"].end(); + + if ((i + 1) % filmSpecimen.saveVTKEveryNthStep == 0) + { + loopTP["save vtk"].start(); + WALBERLA_LOG_INFO_ON_ROOT(CYAN << " SAVING VTK " << RESET); + vtkWriter->write(true); + loopTP["save vtk"].end(); + } + if ((i + 1) % filmSpecimen.saveEnergyEveryNthStep == 0) + { + loopTP["save energy"].start(); + WALBERLA_LOG_INFO_ON_ROOT(CYAN << " SAVING ENERGY " << RESET); + ps->forEachParticle(false, + kernel::SelectLocal(), + ac, + [&](const size_t p_idx) + { + stats.kineticEnergy += 0.5_r * ac.getMass(p_idx) * ac.getLinearVelocity(p_idx) * ac.getLinearVelocity(p_idx); + stats.kineticEnergy += 0.5_r * ac.getAngularVelocity(p_idx) * ac.getInertiaBF(p_idx) * ac.getAngularVelocity(p_idx); + }); + walberla::mpi::reduceInplace(stats, walberla::mpi::SUM); + WALBERLA_ROOT_SECTION() + { + statistics.push_back(stats); + saveStatistics(filmSpecimen.energyFolder + "/statistics.txt", statistics); + } + loopTP["save energy"].end(); + } + if ((i + 1) % filmSpecimen.saveConfEveryNthStep == 0) + { + loopTP["save config"].start(); + WALBERLA_LOG_INFO_ON_ROOT(CYAN << " SAVING CONFIG " << RESET); + saveConfig(ps, + filmSpecimen.confFolder + "/conf_" + std::to_string((i + 1) * 0.00002) + "ns", + IO_MODE::USE_MPI_IO); + loopTP["save config"].end(); + } + } + globalTP["sim loop"].end(); + + auto loopTPReduced = loopTP.getReduced(); + WALBERLA_LOG_DEVEL_ON_ROOT(*loopTPReduced); + auto globalTPReduced = globalTP.getReduced(); + WALBERLA_LOG_DEVEL_ON_ROOT(*globalTPReduced); + auto ttReduced = tt.getReduced(); + WALBERLA_LOG_DEVEL_ON_ROOT(ttReduced); + + numParticles = 0; + int64_t numGhostParticles = 0; + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + [&](const size_t idx) + { + if (data::particle_flags::isSet( ac.getFlagsRef(idx), data::particle_flags::GHOST)) + { + ++numGhostParticles; + } else + { + ++numParticles; + } + }); + + walberla::mpi::reduceInplace(numParticles, walberla::mpi::SUM); + walberla::mpi::reduceInplace(numGhostParticles, walberla::mpi::SUM); + walberla::mpi::reduceInplace(contactsDetected, walberla::mpi::SUM); + walberla::mpi::reduceInplace(contactsTreated, walberla::mpi::SUM); + + + WALBERLA_ROOT_SECTION() + { + std::map<std::string, walberla::int64_t> integerProperties; + std::map<std::string, double> realProperties; + std::map<std::string, std::string> stringProperties; + + addBuildInfoToSQL(integerProperties, realProperties, stringProperties); + addDomainPropertiesToSQL(*forest, integerProperties, realProperties, stringProperties); + addSlurmPropertiesToSQL(integerProperties, realProperties, stringProperties); + + integerProperties["num_particles"] = numParticles; + integerProperties["num_ghost_particles"] = numGhostParticles; + + integerProperties["contacts_detected"] = contactsDetected; + integerProperties["contacts_treated"] = contactsTreated; + + auto runId = sqlite::storeRunInSqliteDB(filmSpecimen.sqlFile, + integerProperties, + stringProperties, + realProperties); + sqlite::storeTimingPoolInSqliteDB(filmSpecimen.sqlFile, runId, *loopTPReduced, "loop"); + sqlite::storeTimingPoolInSqliteDB(filmSpecimen.sqlFile, runId, *globalTPReduced, "global"); + sqlite::storeTimingTreeInSqliteDB(filmSpecimen.sqlFile, runId, tt, "tt"); + } + + return EXIT_SUCCESS; +} + +} // namespace mesa_pd +} // namespace walberla + +int main(int argc, char *argv[]) +{ + return walberla::mesa_pd::main(argc, argv); +} + diff --git a/apps/benchmarks/CNT/CMakeLists.txt b/apps/benchmarks/CNT/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..41c52ccc8eb335732ecd0159128b017811da6975 --- /dev/null +++ b/apps/benchmarks/CNT/CMakeLists.txt @@ -0,0 +1,10 @@ +waLBerla_link_files_to_builddir( *.dat ) + +waLBerla_add_executable( NAME 01_cnt_film + FILES 01_cnt_film.cpp + Config.cpp + FilmSpecimen.cpp + InitializeCNTs.cpp + SQLProperties.cpp + Statistics.cpp + DEPENDS blockforest core mesa_pd sqlite vtk ) diff --git a/apps/benchmarks/CNT/Config.cpp b/apps/benchmarks/CNT/Config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee19d2a97e224628c162af49a4c8f64822305a12 --- /dev/null +++ b/apps/benchmarks/CNT/Config.cpp @@ -0,0 +1,108 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "Config.h" +#include "TerminalColors.h" + +#include "core/mpi/Gatherv.h" +#include "core/mpi/MPIIO.h" +#include "core/mpi/RecvBuffer.h" +#include "core/mpi/SendBuffer.h" + +namespace walberla { +namespace mesa_pd { + +void saveConfig(const shared_ptr<data::ParticleStorage>& ps, + const std::string& filename, + const IO_MODE io_mode) +{ + mpi::SendBuffer sb; + + for (const auto& p : *ps) + { + using namespace walberla::mesa_pd::data::particle_flags; + if (isSet(p.getFlags(), GHOST)) continue; //skip ghosts + + sb << static_cast<int64_t> (p.getSegmentID()); + sb << static_cast<int64_t> (p.getClusterID()); +// sb << static_cast<int64_t> (p.getGroupID()); + + sb << static_cast<double> (p.getPosition()[0]); + sb << static_cast<double> (p.getPosition()[1]); + sb << static_cast<double> (p.getPosition()[2]); + + Vec3 orient = p.getRotation().getMatrix() * Vec3(1,0,0); + // Now orient has the shape (sin(th)cos(ph), sin(th)sin(ph), cos(th)) + sb << static_cast<double> (std::acos(orient[2])); + sb << static_cast<double> (std::atan2(orient[1], orient[0])); + + sb << static_cast<double> (p.getLinearVelocity()[0]); + sb << static_cast<double> (p.getLinearVelocity()[1]); + sb << static_cast<double> (p.getLinearVelocity()[2]); + + sb << static_cast<double> (p.getAngularVelocity()[0]); + sb << static_cast<double> (p.getAngularVelocity()[1]); + sb << static_cast<double> (p.getAngularVelocity()[2]); + } + + switch (io_mode) + { + case IO_MODE::REDUCE_TO_ROOT: + { + WALBERLA_LOG_INFO_ON_ROOT(CYAN << "Saving configuration (reduce to root): " << filename << RESET); + walberla::mpi::RecvBuffer rb; + walberla::mpi::gathervBuffer(sb, rb); + WALBERLA_ROOT_SECTION() + { + uint_t dataSize = sizeof(mpi::RecvBuffer::ElementType) * rb.size(); + std::ofstream binfile; + binfile.open(filename + ".sav", + std::ios::out | std::ios::binary); + binfile.write(reinterpret_cast< const char * >(rb.ptr()), numeric_cast<std::streamsize>(dataSize)); + binfile.close(); + } + break; + } + case IO_MODE::USE_MPI_IO: + { + WALBERLA_LOG_INFO_ON_ROOT(CYAN << "Saving configuration (MPIIO): " << filename << RESET); + walberla::mpi::writeMPIIO(filename + ".mpiio", sb); + break; + } + case IO_MODE::ONE_FILE_PER_RANK: + { + WALBERLA_LOG_INFO_ON_ROOT(CYAN << "Saving configuration (one file per process): " << filename << RESET); + uint_t dataSize = sizeof(mpi::SendBuffer::ElementType) * sb.size(); + std::ofstream binfile; + binfile.open(filename + "_" + std::to_string(mpi::MPIManager::instance()->rank()) + ".sav", + std::ios::out | std::ios::binary); + binfile.write(reinterpret_cast< const char * >(sb.ptr()), numeric_cast<std::streamsize>(dataSize)); + binfile.close(); + } + break; + default: + WALBERLA_ABORT("Unknown IO_MODE"); + } +} + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/Config.h b/apps/benchmarks/CNT/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..d21d2bf0c60973dfdad7c274d21251e497d1bd7d --- /dev/null +++ b/apps/benchmarks/CNT/Config.h @@ -0,0 +1,37 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "mesa_pd/data/ParticleStorage.h" + +namespace walberla { +namespace mesa_pd { + +enum class IO_MODE {REDUCE_TO_ROOT, USE_MPI_IO, ONE_FILE_PER_RANK}; + +void saveConfig(const shared_ptr<data::ParticleStorage>& ps, + const std::string& filename, + const IO_MODE io_mode); + +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/apps/benchmarks/CNT/FilmSpecimen.cpp b/apps/benchmarks/CNT/FilmSpecimen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..460360e7f5002ba0fced1e62ab943da911c7393a --- /dev/null +++ b/apps/benchmarks/CNT/FilmSpecimen.cpp @@ -0,0 +1,122 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include "FilmSpecimen.h" +#include "TerminalColors.h" + +#include <core/logging/Logging.h> + +namespace walberla { +namespace mesa_pd { + +void loadFromConfig(FilmSpecimen& params, const Config::BlockHandle& cfg) +{ + WALBERLA_LOG_INFO_ON_ROOT(GREEN << "Loading CNT film setup: " << RESET) + params.sizeX = cfg.getParameter<real_t>("sizeX", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "sizeX: " << GREEN << params.sizeX << RESET); + + params.sizeY = cfg.getParameter<real_t>("sizeY", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "sizeY: " << GREEN << params.sizeY << RESET); + + params.sizeZ = cfg.getParameter<real_t>("sizeZ", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "sizeZ: " << GREEN << params.sizeZ << RESET); + + params.oopp = cfg.getParameter<bool>("oopp", false ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "oopp: " << GREEN << params.oopp << RESET); + + params.numBlocksX = cfg.getParameter<uint_t>("numBlocksX", 1 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "numBlocksX: " << GREEN << params.numBlocksX << RESET); + + params.numBlocksY = cfg.getParameter<uint_t>("numBlocksY", 1 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "numBlocksY: " << GREEN << params.numBlocksY << RESET); + + params.numBlocksZ = cfg.getParameter<uint_t>("numBlocksZ", 1 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "numBlocksZ: " << GREEN << params.numBlocksZ << RESET); + + params.min_OOP = cfg.getParameter<real_t>("min_OOP", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "min_OOP: " << GREEN << params.min_OOP << RESET); + + params.max_OOP = cfg.getParameter<real_t>("max_OOP", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "max_OOP: " << GREEN << params.max_OOP << RESET); + + params.numCNTs = cfg.getParameter<int>("numCNTs", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "numCNTs: " << GREEN << params.numCNTs << RESET); + + params.numSegs = cfg.getParameter<int>("numSegs", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "numSegs: " << GREEN << params.numSegs << RESET); + + params.spacing = cfg.getParameter<real_t>("spacing", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "spacing: " << GREEN << params.spacing << RESET); + + params.localDamping = cfg.getParameter<real_t>("localDamping", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "localDamping: " << GREEN << params.localDamping << RESET); + + params.viscousDamping = cfg.getParameter<real_t>("viscousDamping", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "viscousDamping: " << GREEN << params.viscousDamping << RESET); + + params.seed = cfg.getParameter<uint_t>("seed", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "seed: " << GREEN << params.seed << RESET); + + params.vdW = cfg.getParameter<int>("vdW", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "vdW: " << GREEN << params.vdW << RESET); + + params.simulationSteps = cfg.getParameter<int>("simulationSteps", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "simulationSteps: " << GREEN << params.simulationSteps << RESET); + + params.saveVTKEveryNthStep = cfg.getParameter<int>("saveVTKEveryNthStep", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "saveVTKEveryNthStep: " << GREEN << params.saveVTKEveryNthStep << RESET); + + params.saveEnergyEveryNthStep = cfg.getParameter<int>("saveEnergyEveryNthStep", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "saveEnergyEveryNthStep: " << GREEN << params.saveEnergyEveryNthStep << RESET); + + params.saveConfEveryNthStep = cfg.getParameter<int>("saveConfEveryNthStep", 0 ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "saveConfEveryNthStep: " << GREEN << params.saveConfEveryNthStep << RESET); + + params.vtkFolder = cfg.getParameter<std::string>("vtkFolder", "." ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "vtkFolder: " << GREEN << params.vtkFolder << RESET); + + params.energyFolder = cfg.getParameter<std::string>("energyFolder", "." ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "energyFolder: " << GREEN << params.energyFolder << RESET); + + params.confFolder = cfg.getParameter<std::string>("confFolder", "." ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "confFolder: " << GREEN << params.confFolder << RESET); + + params.useMPIIO = cfg.getParameter<bool>("useMPIIO", false ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "useMPIIO: " << GREEN << params.useMPIIO << RESET); + + params.sqlFile = cfg.getParameter<std::string>("sqlFile", "cnt.sqlite" ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "sqlFile: " << GREEN << params.sqlFile << RESET); + + params.initialConfigurationFile = cfg.getParameter<std::string>("initialConfigurationFile", "" ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "initialConfigurationFile: " << GREEN << params.initialConfigurationFile << RESET); + +} + +} //namespace mesa_pd +} //namespace walberla + diff --git a/apps/benchmarks/CNT/FilmSpecimen.h b/apps/benchmarks/CNT/FilmSpecimen.h new file mode 100644 index 0000000000000000000000000000000000000000..5aa041f9e182d02e0c5a181998c690d20e078747 --- /dev/null +++ b/apps/benchmarks/CNT/FilmSpecimen.h @@ -0,0 +1,72 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include "core/config/Config.h" + +#include <string> + +namespace walberla { +namespace mesa_pd { + +struct FilmSpecimen +{ + real_t sizeX = 0; //Specimen length (x direction) + real_t sizeY = 0; //Specimen length (y direction) + real_t sizeZ = 0; //Specimen length (z direction) + bool oopp = false; //Specimen out-of-plane periodicity (0 - film, 1 - cnt material) + uint_t numBlocksX = 1; //Number of blocks in x direction + uint_t numBlocksY = 1; //Number of blocks in y direction + uint_t numBlocksZ = 1; //Number of blocks in z direction + real_t min_OOP = 0; //Out-of-plane angle minimum + real_t max_OOP = 0; //Out-of-plane angle maximum + int numCNTs = 0; //Number of CNTs + int numSegs = 0; //Number of segments in a CNT + real_t spacing = 0; //Segment half-spacing + real_t localDamping = 0; //Local damping coefficient + real_t viscousDamping = 0; //Viscous damping coefficient + uint_t seed = 0; //random generator seed + int vdW = 0; //type of vdW interaction model + int simulationSteps = 0; //Relaxation duration + int saveVTKEveryNthStep = 0; //timesteps between saving VTK outputs + int saveEnergyEveryNthStep = 0; //timesteps between saving energies + int saveConfEveryNthStep = 0; //timesteps between saving confs + std::string vtkFolder = "."; //Folder for VTK files + std::string energyFolder = "."; //Folder for energy files + std::string confFolder = "."; //Folder for conf files + bool useMPIIO = false; //Write a single file instead of one file per process + std::string sqlFile = "cnt.sqlite"; //database file + std::string initialConfigurationFile = ""; //restart from checkpoint +}; + +void loadFromConfig(FilmSpecimen& params, + const Config::BlockHandle& cfg); + +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/apps/benchmarks/CNT/FilmSpecimen.templ.cpp b/apps/benchmarks/CNT/FilmSpecimen.templ.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1203c455c24045f502c4538145e14b56544f5c0a --- /dev/null +++ b/apps/benchmarks/CNT/FilmSpecimen.templ.cpp @@ -0,0 +1,49 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include "FilmSpecimen.h" +#include "TerminalColors.h" + +#include <core/logging/Logging.h> + +namespace walberla { +namespace mesa_pd { + +void loadFromConfig(FilmSpecimen& params, const Config::BlockHandle& cfg) +{ + WALBERLA_LOG_INFO_ON_ROOT(GREEN << "Loading CNT film setup: " << RESET) + {%- for param in parameters %} + params.{{param.name}} = cfg.getParameter<{{param.type}}>("{{param.name}}", {{param.defValue}} ); + WALBERLA_LOG_INFO_ON_ROOT(YELLOW << "{{param.name}}: " << GREEN << params.{{param.name}} << RESET); + {% endfor %} +} + +} //namespace mesa_pd +} //namespace walberla + + diff --git a/apps/benchmarks/CNT/FilmSpecimen.templ.h b/apps/benchmarks/CNT/FilmSpecimen.templ.h new file mode 100644 index 0000000000000000000000000000000000000000..a5eec2182f69181c67097ea8bb0d8c79a31633f4 --- /dev/null +++ b/apps/benchmarks/CNT/FilmSpecimen.templ.h @@ -0,0 +1,49 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include "core/config/Config.h" + +#include <string> + +namespace walberla { +namespace mesa_pd { + +struct FilmSpecimen +{ + {%- for param in parameters %} + {{param.type}} {{param.name}} = {{param.defValue}}; //{{param.comment}} + {%- endfor %} +}; + +void loadFromConfig(FilmSpecimen& params, + const Config::BlockHandle& cfg); + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/FilmSpecimenGenerator.py b/apps/benchmarks/CNT/FilmSpecimenGenerator.py new file mode 100644 index 0000000000000000000000000000000000000000..4b91cd1f3a7c3b930285e7ca16c3c1d3dd174238 --- /dev/null +++ b/apps/benchmarks/CNT/FilmSpecimenGenerator.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +from jinja2 import Environment, FileSystemLoader +import os + + +class Parameter: + def __init__(self, name, type, defValue="", comment=""): + """Propery of a data strcuture + + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + comment : str + comment appended to the properties in the header file + """ + + self.name = name + self.type = type + self.defValue = defValue + self.comment = comment + + def __str__(self): + return "name: {}, type: {}, defValue: {} \\\\{}".format(self.name, self.type, self.defValue, self.comment) + + +class Config: + def __init__(self): + self.parameters = [] + + def parameter_exists(self, name): + for v in self.parameters: + if v.name == name: + return True + return False + + def add_parameter(self, name, type, defValue, comment): + if self.parameter_exists(name): + print("parameters already added: " + name) + else: + self.parameters.append(Parameter(name, type, defValue, comment)) + + def generate_file(self, template): + context = dict() + context["parameters"] = self.parameters + + path = "" + filename = template.replace(".templ", "") + dirname = os.path.dirname(__file__) + env = Environment(loader=FileSystemLoader(dirname)) + print("generating: " + path + filename) + with open(path + filename, "wb") as fout: + content = env.get_template(template).render(context) + fout.write(content.encode('utf8')) + + def generate(self): + print("=" * 90) + print("Config File:") + print("") + print("{0: <30}{1: <30}{2: <30}".format("Name", "Type", "Def. Value")) + print("=" * 90) + for param in self.parameters: + print("{0: <30.29}{1: <30.29}{2: <30.29}".format(param.name, param.type, param.defValue)) + print("=" * 90) + + self.generate_file("FilmSpecimen.templ.h") + self.generate_file("FilmSpecimen.templ.cpp") + + diff --git a/apps/benchmarks/CNT/GenerateFilmSpecimen.py b/apps/benchmarks/CNT/GenerateFilmSpecimen.py new file mode 100755 index 0000000000000000000000000000000000000000..7bc9a3868294ad08a4402bb81caf76fb436f1e00 --- /dev/null +++ b/apps/benchmarks/CNT/GenerateFilmSpecimen.py @@ -0,0 +1,36 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- + +from FilmSpecimenGenerator import Config + +cfg = Config() +cfg.add_parameter("sizeX", "real_t", "0", "Specimen length (x direction)") +cfg.add_parameter("sizeY", "real_t", "0", "Specimen length (y direction)") +cfg.add_parameter("sizeZ", "real_t", "0", "Specimen length (z direction)") +cfg.add_parameter("oopp", "bool", "false", "Specimen out-of-plane periodicity (0 - film, 1 - cnt material)") +cfg.add_parameter("numBlocksX", "uint_t", "1", "Number of blocks in x direction") +cfg.add_parameter("numBlocksY", "uint_t", "1", "Number of blocks in y direction") +cfg.add_parameter("numBlocksZ", "uint_t", "1", "Number of blocks in z direction") +cfg.add_parameter("min_OOP", "real_t", "0", "Out-of-plane angle minimum") +cfg.add_parameter("max_OOP", "real_t", "0", "Out-of-plane angle maximum") +cfg.add_parameter("numCNTs", "int", "0", "Number of CNTs") +cfg.add_parameter("numSegs", "int", "0", "Number of segments in a CNT") +cfg.add_parameter("spacing", "real_t", "0", "Segment half-spacing") +cfg.add_parameter("localDamping", "real_t", "0", "Local damping coefficient") +cfg.add_parameter("viscousDamping", "real_t", "0", "Viscous damping coefficient") +cfg.add_parameter("seed", "uint_t", "0", "random generator seed") +cfg.add_parameter("vdW", "int", "0", "type of vdW interaction model") +cfg.add_parameter("simulationSteps", "int", "0", "Relaxation duration") +cfg.add_parameter("saveVTKEveryNthStep", "int", "0", "timesteps between saving VTK outputs") +cfg.add_parameter("saveEnergyEveryNthStep", "int", "0", "timesteps between saving energies") +cfg.add_parameter("saveConfEveryNthStep", "int", "0", "timesteps between saving confs") +cfg.add_parameter("vtkFolder", "std::string", '"."', "Folder for VTK files") +cfg.add_parameter("energyFolder", "std::string", '"."', "Folder for energy files") +cfg.add_parameter("confFolder", "std::string", '"."', "Folder for conf files") +cfg.add_parameter("useMPIIO", "bool", "false", "Write a single file instead of one file per process") +cfg.add_parameter("sqlFile", "std::string", '"cnt.sqlite"', "database file") +cfg.add_parameter("initialConfigurationFile", "std::string", '""', "restart from checkpoint") + +cfg.generate() + + diff --git a/apps/benchmarks/CNT/InitializeCNTs.cpp b/apps/benchmarks/CNT/InitializeCNTs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da93903538c7fbb1f0da84ef60c733a2ec2fcf2c --- /dev/null +++ b/apps/benchmarks/CNT/InitializeCNTs.cpp @@ -0,0 +1,174 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "InitializeCNTs.h" +#include "TerminalColors.h" + +#include "core/math/Constants.h" +#include "core/math/Random.h" +#include "core/mpi/MPIManager.h" +#include "mesa_pd/kernel/cnt/Parameters.h" + +#include <cmath> + +namespace walberla{ +namespace mesa_pd { + +int64_t generateCNTs(const FilmSpecimen& spec, + const shared_ptr<data::ParticleStorage>& ps, + const domain::IDomain& domain) +{ + auto myRank = mpi::MPIManager::instance()->rank(); + + auto CNT_length = 2_r * spec.spacing * real_c(spec.numSegs); + // Fixed random seed is necessary for coordinated generation on all MPI proc. + auto rand0_1 = math::RealRandom<real_t>(static_cast<std::mt19937::result_type>(spec.seed)); + // Create an assembly of CNTs + int64_t numParticles = 0; + for (int tube = 0; tube < spec.numCNTs; tube++) + { + // This definition of theta provides uniform distribution of random orientations on a sphere when spec.OutOfPlane = 1. + real_t theta = 0.5_r * math::pi * spec.min_OOP + (spec.max_OOP - spec.min_OOP) * std::acos(1_r - rand0_1()); + real_t phi = 2_r * math::pi * rand0_1(); + real_t pos_x = spec.sizeX * rand0_1(); + real_t pos_y = spec.sizeY * rand0_1(); + real_t pos_z = spec.sizeZ * rand0_1(); + + for (int segment = 0; segment < spec.numSegs; segment++) + { + // Generate segment position + Vec3 pos; + auto r = -0.5_r * CNT_length + 2_r * spec.spacing * real_c(segment); + pos[0] = pos_x + r * std::sin(theta) * std::cos(phi); + pos[1] = pos_y + r * std::sin(theta) * std::sin(phi); + pos[2] = pos_z + r * std::cos(theta); + + // Account for periodicity (will not work if CNTs are longer than domain size) + if ((pos[0] > spec.sizeX)) pos[0] -= spec.sizeX; + if ((pos[0] < 0)) pos[0] += spec.sizeX; + if ((pos[1] > spec.sizeY)) pos[1] -= spec.sizeY; + if ((pos[1] < 0)) pos[1] += spec.sizeY; + if (spec.oopp) + { + if ((pos[2] > spec.sizeZ)) pos[2] -= spec.sizeZ; + if ((pos[2] < 0)) pos[2] += spec.sizeZ; + } + + //Only create segment if it is located on the process. + if (domain.isContainedInProcessSubdomain(uint_c(myRank), pos)) + { + data::Particle &&sp = *ps->create(); + sp.setPosition(pos); + sp.setOwner(myRank); + sp.setInteractionRadius(kernel::cnt::outer_radius); + sp.setSegmentID(segment); + sp.setClusterID(tube); + sp.getRotationRef().rotate( Vec3(0_r, 1_r, 0_r), -0.5_r * math::pi + theta); + sp.getRotationRef().rotate( Vec3(0_r, 0_r, 1_r), phi); + numParticles++; + } + } + } + + return numParticles; +} + +int64_t loadCNTs(const std::string& filename, + const shared_ptr<data::ParticleStorage>& ps) +{ + WALBERLA_LOG_INFO_ON_ROOT(GREEN << "Loading configuration (binary format): " << filename); + const auto numProcesses = mpi::MPIManager::instance()->numProcesses(); + const auto rank = mpi::MPIManager::instance()->rank(); + //---------Generation of WaLBerla model--------------------------------------------------------------------------------------------------------------------------------- + // Note that walberla primitives are created below only on MPI process that is responsible + // for this branch of blockforest + + int64_t numParticles = 0; + + for (auto i = 0; i < numProcesses; ++i) + { + WALBERLA_MPI_BARRIER(); + if (i != rank) continue; //bad practice but with the current file format we have to do this + std::ifstream binfile; + binfile.open(filename.c_str(), std::ios::in | std::ios::binary); + int size; + binfile.read((char *) &size, sizeof(int)); + std::cout << RED << "size read form binary file is" << size << RESET << std::endl; + for (int id = 0; id < size; id++) + { + int ID; + int sID; + int cID; + int gID; + double x; + double y; + double z; + double theta; + double phi; + double vx; + double vy; + double vz; + double wx; + double wy; + double wz; + binfile.read((char *) &ID, sizeof(int)); + binfile.read((char *) &sID, sizeof(int)); + binfile.read((char *) &cID, sizeof(int)); + binfile.read((char *) &gID, sizeof(int)); + binfile.read((char *) &x, sizeof(double)); + binfile.read((char *) &y, sizeof(double)); + binfile.read((char *) &z, sizeof(double)); + binfile.read((char *) &theta, sizeof(double)); + binfile.read((char *) &phi, sizeof(double)); + binfile.read((char *) &vx, sizeof(double)); + binfile.read((char *) &vy, sizeof(double)); + binfile.read((char *) &vz, sizeof(double)); + binfile.read((char *) &wx, sizeof(double)); + binfile.read((char *) &wy, sizeof(double)); + binfile.read((char *) &wz, sizeof(double)); + Vec3 pos; + pos[0] = real_c(x); + pos[1] = real_c(y); + pos[2] = real_c(z); + + data::Particle &&sp = *ps->create(); + sp.setPosition(pos); + sp.setOwner(rank); + sp.setInteractionRadius(kernel::cnt::outer_radius); + sp.setSegmentID(sID); + sp.setClusterID(cID); + sp.getRotationRef().rotate( Vec3(0_r, 1_r, 0_r), -0.5_r * math::pi + real_c(theta)); + sp.getRotationRef().rotate( Vec3(0_r, 0_r, 1_r), real_c(phi)); + sp.setLinearVelocity( Vec3(real_c(vx), real_c(vy), real_c(vz)) ); + sp.setAngularVelocity( Vec3(real_c(wx), real_c(wy), real_c(wz)) ); + numParticles++; + } + } + + mpi::reduceInplace(numParticles, mpi::SUM); + WALBERLA_LOG_INFO_ON_ROOT("#particles created: " << numParticles); + + return numParticles; +} + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/InitializeCNTs.h b/apps/benchmarks/CNT/InitializeCNTs.h new file mode 100644 index 0000000000000000000000000000000000000000..501753fb04706923dbc552b198e2a3f98d2d15d2 --- /dev/null +++ b/apps/benchmarks/CNT/InitializeCNTs.h @@ -0,0 +1,41 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "FilmSpecimen.h" + +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/domain/IDomain.h" + +namespace walberla{ +namespace mesa_pd { + +int64_t generateCNTs(const FilmSpecimen& spec, + const shared_ptr<data::ParticleStorage>& ps, + const domain::IDomain& domain); + +int64_t loadCNTs(const std::string& filename, + const shared_ptr<data::ParticleStorage>& ps); + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/SQLProperties.cpp b/apps/benchmarks/CNT/SQLProperties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3daa67d5763ad5732cc6462da5f9df76e9304c23 --- /dev/null +++ b/apps/benchmarks/CNT/SQLProperties.cpp @@ -0,0 +1,92 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "SQLProperties.h" + +#include <blockforest/BlockForest.h> +#include <core/DataTypes.h> +#include <core/waLBerlaBuildInfo.h> +#include <core/mpi/MPIManager.h> + +namespace walberla { +namespace mesa_pd { + +void addBuildInfoToSQL(std::map<std::string, int64_t> & /*integerProperties*/, + std::map<std::string, double> & /*realProperties*/, + std::map<std::string, std::string> &stringProperties) +{ + stringProperties["walberla_sha"] = walberla::core::buildinfo::gitSHA1(); + stringProperties["build_type"] = walberla::core::buildinfo::buildType(); + stringProperties["compiler_flags"] = walberla::core::buildinfo::compilerFlags(); + stringProperties["build_machine"] = walberla::core::buildinfo::buildMachine(); +} + +void addDomainPropertiesToSQL(const ::walberla::blockforest::BlockForest &forest, + std::map<std::string, int64_t> &integerProperties, + std::map<std::string, double> &realProperties, + std::map<std::string, std::string> & /*stringProperties*/ ) +{ + integerProperties["numMPIProcesses"] = ::walberla::mpi::MPIManager::instance()->numProcesses(); + + realProperties["domainXMin"] = forest.getDomain().xMin(); + realProperties["domainXMax"] = forest.getDomain().xMax(); + realProperties["domainYMin"] = forest.getDomain().yMin(); + realProperties["domainYMax"] = forest.getDomain().yMax(); + realProperties["domainZMin"] = forest.getDomain().zMin(); + realProperties["domainZMax"] = forest.getDomain().zMax(); + + integerProperties["xBlocks"] = ::walberla::int_c(forest.getXSize()); + integerProperties["yBlocks"] = ::walberla::int_c(forest.getYSize()); + integerProperties["zBlocks"] = ::walberla::int_c(forest.getZSize()); + + integerProperties["xPeriodic"] = (forest.isXPeriodic() ? 1 : 0); + integerProperties["yPeriodic"] = (forest.isYPeriodic() ? 1 : 0); + integerProperties["zPeriodic"] = (forest.isZPeriodic() ? 1 : 0); +} + +std::string envToString(const char *env) +{ + return env != nullptr ? std::string(env) : ""; +} + +void addSlurmPropertiesToSQL(std::map<std::string, int64_t> & /*integerProperties*/, + std::map<std::string, double> & /*realProperties*/, + std::map<std::string, std::string> &stringProperties) +{ + stringProperties["SLURM_CLUSTER_NAME"] = envToString(std::getenv("SLURM_CLUSTER_NAME")); + stringProperties["SLURM_CPUS_ON_NODE"] = envToString(std::getenv("SLURM_CPUS_ON_NODE")); + stringProperties["SLURM_CPUS_PER_TASK"] = envToString(std::getenv("SLURM_CPUS_PER_TASK")); + stringProperties["SLURM_JOB_ACCOUNT"] = envToString(std::getenv("SLURM_JOB_ACCOUNT")); + stringProperties["SLURM_JOB_ID"] = envToString(std::getenv("SLURM_JOB_ID")); + stringProperties["SLURM_JOB_CPUS_PER_NODE"] = envToString(std::getenv("SLURM_JOB_CPUS_PER_NODE")); + stringProperties["SLURM_JOB_NAME"] = envToString(std::getenv("SLURM_JOB_NAME")); + stringProperties["SLURM_JOB_NUM_NODES"] = envToString(std::getenv("SLURM_JOB_NUM_NODES")); + stringProperties["SLURM_NTASKS"] = envToString(std::getenv("SLURM_NTASKS")); + stringProperties["SLURM_NTASKS_PER_CORE"] = envToString(std::getenv("SLURM_NTASKS_PER_CORE")); + stringProperties["SLURM_NTASKS_PER_NODE"] = envToString(std::getenv("SLURM_NTASKS_PER_NODE")); + stringProperties["SLURM_NTASKS_PER_SOCKET"] = envToString(std::getenv("SLURM_NTASKS_PER_SOCKET")); + stringProperties["SLURM_CPU_BIND_TYPE"] = envToString(std::getenv("SLURM_CPU_BIND_TYPE")); +} + +} //namespace mesa_pd +} //namespace walberla + diff --git a/apps/benchmarks/CNT/SQLProperties.h b/apps/benchmarks/CNT/SQLProperties.h new file mode 100644 index 0000000000000000000000000000000000000000..de2523b6661aaa606d2ff8832dd67f3ca035b38a --- /dev/null +++ b/apps/benchmarks/CNT/SQLProperties.h @@ -0,0 +1,48 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <blockforest/BlockForest.h> +#include <core/DataTypes.h> + +#include <map> +#include <string> + +namespace walberla { +namespace mesa_pd { + +void addBuildInfoToSQL(std::map<std::string, int64_t> &integerProperties, + std::map<std::string, double> &realProperties, + std::map<std::string, std::string> &stringProperties); + +void addDomainPropertiesToSQL(const walberla::blockforest::BlockForest &forest, + std::map<std::string, int64_t> &integerProperties, + std::map<std::string, double> &realProperties, + std::map<std::string, std::string> & /*stringProperties*/ ); + +void addSlurmPropertiesToSQL(std::map<std::string, int64_t> &integerProperties, + std::map<std::string, double> &realProperties, + std::map<std::string, std::string> &stringProperties); + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/SphericalSegmentAccessor.h b/apps/benchmarks/CNT/SphericalSegmentAccessor.h new file mode 100644 index 0000000000000000000000000000000000000000..820c4db467b63ee87d47d70cd4959e2ae64def33 --- /dev/null +++ b/apps/benchmarks/CNT/SphericalSegmentAccessor.h @@ -0,0 +1,60 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "mesa_pd/data/ParticleAccessor.h" +#include "mesa_pd/kernel/cnt/Parameters.h" + +namespace walberla { +namespace mesa_pd { + +class SphericalSegmentAccessor : public data::ParticleAccessor +{ +public: + SphericalSegmentAccessor(std::shared_ptr<data::ParticleStorage>& ps) + : ParticleAccessor(ps) + {} + + constexpr auto getMass(const size_t /*p_idx*/) const {return kernel::cnt::mass_T;} + walberla::real_t& getMassRef(const size_t /*p_idx*/) {WALBERLA_ABORT("not available");} + void setMass(const size_t /*p_idx*/, walberla::real_t const & /*v*/) {WALBERLA_ABORT("not available");} + + constexpr auto getInvMass(const size_t /*p_idx*/) const {return 1_r / kernel::cnt::mass_T;} + walberla::real_t& getInvMassRef(const size_t /*p_idx*/) {WALBERLA_ABORT("not available");} + void setInvMass(const size_t /*p_idx*/, walberla::real_t const & /*v*/) {WALBERLA_ABORT("not available");} + + constexpr auto& getInertiaBF(const size_t /*p_idx*/) const {return Ia;} + Mat3& getInertiaBFRef(const size_t /*p_idx*/) {WALBERLA_ABORT("not available");} + void setInertiaBF(const size_t /*p_idx*/, Mat3 const & /*v*/) {WALBERLA_ABORT("not available");} + + constexpr auto& getInvInertiaBF(const size_t /*p_idx*/) const {return invI;} + Mat3& getInvInertiaBFRef(const size_t /*p_idx*/) {WALBERLA_ABORT("not available");} + void setInvInertiaBF(const size_t /*p_idx*/, Mat3 const & /*v*/) {WALBERLA_ABORT("not available");} +private: + // - sphere : I = (2/5)*mass*radius^2 + static constexpr auto Ia = 0.4_r * kernel::cnt::mass_T * kernel::cnt::inner_radius * kernel::cnt::inner_radius; + static constexpr auto invI = Mat3(1_r/Ia, 0_r, 0_r, 0_r, 1_r/Ia, 0_r, 0_r, 0_r, 1_r/Ia); +}; + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/benchmarks/CNT/Statistics.cpp b/apps/benchmarks/CNT/Statistics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..febd6f433caefe35d0811f9f0712b464d911e1ef --- /dev/null +++ b/apps/benchmarks/CNT/Statistics.cpp @@ -0,0 +1,70 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "Statistics.h" +#include "TerminalColors.h" + +#include "core/logging/Logging.h" + +#include <fstream> + +namespace walberla { +namespace mesa_pd { + +void saveStatistics(const std::string& filename, + const std::vector<Statistics>& stats) +{ + WALBERLA_LOG_INFO_ON_ROOT(CYAN << "saving statistics: " << filename << RESET); + std::ofstream fout(filename); + fout.precision(10); + fout << "# kineticEnergy vdwEnergy stretchEnergy tensileEnergy shearEnergy bendingEnergy twistingEnergy numAlignedPairs" << std::endl; + for (const auto& stat : stats) + { + fout << stat.kineticEnergy << " " + << stat.vdwEnergy << " " + << stat.stretchEnergy << " " + << stat.tensileEnergy << " " + << stat.shearEnergy << " " + << stat.bendingEnergy << " " + << stat.twistingEnergy << " " + << stat.numAlignedPairs << std::endl; + } + fout.close(); +} + +} //namespace mesa_pd + +namespace mpi { +void reduceInplace( mesa_pd::Statistics& stats, mpi::Operation operation, int recvRank, MPI_Comm comm ) +{ + reduceInplace(stats.kineticEnergy, operation, recvRank, comm); + reduceInplace(stats.vdwEnergy, operation, recvRank, comm); + reduceInplace(stats.stretchEnergy, operation, recvRank, comm); + reduceInplace(stats.tensileEnergy, operation, recvRank, comm); + reduceInplace(stats.shearEnergy, operation, recvRank, comm); + reduceInplace(stats.bendingEnergy, operation, recvRank, comm); + reduceInplace(stats.twistingEnergy, operation, recvRank, comm); + reduceInplace(stats.numAlignedPairs, operation, recvRank, comm); +} +} //namespace mpi + +} //namespace walberla \ No newline at end of file diff --git a/apps/benchmarks/CNT/Statistics.h b/apps/benchmarks/CNT/Statistics.h new file mode 100644 index 0000000000000000000000000000000000000000..51f614cc59423215dd436181e13419984dfc1f6b --- /dev/null +++ b/apps/benchmarks/CNT/Statistics.h @@ -0,0 +1,54 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "core/mpi/Reduce.h" + +#include <string> +#include <vector> + +namespace walberla { +namespace mesa_pd { + +struct Statistics +{ + real_t kineticEnergy = 0_r; + real_t vdwEnergy = 0_r; + real_t stretchEnergy = 0_r; + real_t tensileEnergy = 0_r; + real_t shearEnergy = 0_r; + real_t bendingEnergy = 0_r; + real_t twistingEnergy = 0_r; + int64_t numAlignedPairs = 0; +}; + +void saveStatistics(const std::string& filename, + const std::vector<Statistics>& stats); + +} //namespace mesa_pd + +namespace mpi { +void reduceInplace( mesa_pd::Statistics& stats, mpi::Operation operation, int recvRank = 0, MPI_Comm comm = MPI_COMM_WORLD ); +} //namespace mpi + +} //namespace walberla diff --git a/apps/benchmarks/CNT/TerminalColors.h b/apps/benchmarks/CNT/TerminalColors.h new file mode 100644 index 0000000000000000000000000000000000000000..e572dffec5e357eda894ff9e93d8ba43989cbc3e --- /dev/null +++ b/apps/benchmarks/CNT/TerminalColors.h @@ -0,0 +1,49 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <string> + +namespace walberla { + +#ifdef PLAIN_OUTPUT +//----Terminal color manipulators----- +const std::string RED(""); // errors and problems +const std::string GREEN(""); // loading operations +const std::string YELLOW(""); // information (non-Walberla) +const std::string PURPLE(""); // stages of program implementation +const std::string CYAN(""); // save/write operations +const std::string RESET(""); +//==================================== +#else +//----Terminal color manipulators----- +const std::string RED("\033[1;31m"); // errors and problems +const std::string GREEN("\033[1;32m"); // loading operations +const std::string YELLOW("\033[1;33m"); // information (non-Walberla) +const std::string PURPLE("\033[1;35m"); // stages of program implementation +const std::string CYAN("\033[1;36m"); // save/write operations +const std::string RESET("\033[0m"); +//==================================== +#endif + +} //namespace walberla \ No newline at end of file diff --git a/apps/benchmarks/CNT/specimen_setup.dat b/apps/benchmarks/CNT/specimen_setup.dat new file mode 100644 index 0000000000000000000000000000000000000000..19703ed28bf6a12cb29f40f46630bc3869c0ab8c --- /dev/null +++ b/apps/benchmarks/CNT/specimen_setup.dat @@ -0,0 +1,30 @@ +//--------------CNT material generator input file (do not change anything except numerical values!)- +// This file sets up generation of a rectangular specimen of a CNT material +// At the generation stage, triple periodic boundary conditions are imposed. +// Out-of-plane (xy) angle span tunes transverse anizotropy of the film (1 means isotropy) +// Note that the numerical values should be single space separated + +CNT +{ + sizeX 20000; // A - Specimen length (x direction). + sizeY 20000; // A - Specimen width (y direction). + sizeZ 200; // A - Specimen height (z direction). + oopp 0; // - out of plane periodicity + numBlocksX 2; // - Number of blocks in x direction (blocks are distributed over available MPI processes, + numBlocksY 2; // - Number of blocks in y direction nx x ny x nz blocks total + numBlocksZ 1; // - Number of blocks in z direction (nx, ny, nz can not be less than 2 ) + min_OOP 0.995; // (in PI/2 rads) - minimum theta angle (set 0 for isotropy) + max_OOP 1.0; // (in PI/2 rads) - maximum theta angle (set 1 for isotropy) + numCNTs 1000; // - Number of CNTs. + numSegs 800; // - Number of segments in a CNT. + spacing 6.78; // - Segment spacing + localDamping 0.2; // - "local" damping + viscousDamping 0.00; // - viscous damping + seed 1201; // - random seed - needs to be changed for a different realization + vdW 1; // - vdW model (0 - isotr.vdW (comp speed-1.0), 1 - aniz. vdW (comp speed 0.54), 2 - numer.integrated vdW (comp-speed 0.14)) + simulationSteps 1000000; // - timesteps relaxation duration + saveEveryNthStep 10000; // - timesteps between checkpoints + saveConfEveryNthStep 100000; // - timesteps between saving confs + file serie_3_spec_1; // - filename to save the resulting conf (saved to ../confs/) +} +//================================================================================================== diff --git a/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h b/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h index df369216e4d5e808ab9c5567897ae13ac7c35f85..5beb8622bed219a931b8264fdf8c750fe1dc5b65 100644 --- a/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h +++ b/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h @@ -81,6 +81,8 @@ void AnisotropicVDWContact::operator()(const size_t p_idx1, const size_t p_idx2, Accessor &ac) { + isParallel_ = false; + energy_ = 0_r; //===Adaptation of PFC5 vdW contact model implementation==== // Getting the orientations of segments @@ -128,7 +130,6 @@ void AnisotropicVDWContact::operator()(const size_t p_idx1, // check that cosine belongs [-1,1] cos_gamma = std::min(1.0_r, cos_gamma); cos_gamma = std::max(-1.0_r, cos_gamma); - isParallel_ = false; if (L < 20_r && L > 16_r) { const auto gamma = acos(cos_gamma); @@ -373,7 +374,6 @@ void AnisotropicVDWContact::operator()(const size_t p_idx1, } else if (L <= 2_r * R_ * 1.2_r * TH) { // Small distance //WALBERLA_LOG_DEVEL( "Small distance"); - energy_ = 0_r; real_t F = -1_r; addForceAtomic(p_idx1, ac, F * n); addForceAtomic(p_idx2, ac, -F * n); diff --git a/src/mesa_pd/kernel/cnt/Parameters.h b/src/mesa_pd/kernel/cnt/Parameters.h index c265088bab02da9837599fbf333032b795bf2b0d..fc4b98f7f666a6fc6707ba13fbeb12bcf2c91ef5 100644 --- a/src/mesa_pd/kernel/cnt/Parameters.h +++ b/src/mesa_pd/kernel/cnt/Parameters.h @@ -80,10 +80,10 @@ constexpr auto M_C = 12.011_r; constexpr auto mass_T = ro * T * M_C * 104.397_r; /// Volume of a capsule -double vol_capsule = (4_r/3_r) * math::pi * (R_CNT * R_CNT * R_CNT) + math::pi * R_CNT * R_CNT * T; +const double vol_capsule = (4_r/3_r) * math::pi * (R_CNT * R_CNT * R_CNT) + math::pi * R_CNT * R_CNT * T; /// Density of a capsule -double dens_capsule = mass_T / vol_capsule; +const double dens_capsule = mass_T / vol_capsule; /// V-bond parameter constexpr auto knorm = (En * 0.006242_r) / T; diff --git a/src/mesa_pd/kernel/cnt/VBondContact.h b/src/mesa_pd/kernel/cnt/VBondContact.h index 6bc5edf98e7bdb8c3adee076a712ea42bc15dccf..dc252756c77631bf3efc9b1a3cc6eaf6d5bef301 100644 --- a/src/mesa_pd/kernel/cnt/VBondContact.h +++ b/src/mesa_pd/kernel/cnt/VBondContact.h @@ -106,6 +106,11 @@ void VBondContact::operator()(const size_t p_idx1, const size_t p_idx2, Accessor &ac) { + tensileEnergy = 0_r; + shearEnergy = 0_r; + bendingEnergy = 0_r; + twistingEnergy = 0_r; + Vec3 ri = ac.getPosition(p_idx1); Vec3 rj = ac.getPosition(p_idx2);