diff --git a/apps/showcases/CMakeLists.txt b/apps/showcases/CMakeLists.txt index 536f56ff6acdbdb102faf394361bb2fd661af6e8..266582c2283dca2e7d8dd44973a1e6517027fb46 100644 --- a/apps/showcases/CMakeLists.txt +++ b/apps/showcases/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory( BidisperseFluidizedBed ) add_subdirectory( CombinedResolvedUnresolved ) +add_subdirectory( HeatConduction ) add_subdirectory( Mixer ) diff --git a/apps/showcases/HeatConduction/CMakeLists.txt b/apps/showcases/HeatConduction/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f9465cda0679d5d0708213892a509bcc211c5bfc --- /dev/null +++ b/apps/showcases/HeatConduction/CMakeLists.txt @@ -0,0 +1,5 @@ +waLBerla_link_files_to_builddir( *.cfg ) + +waLBerla_add_executable( NAME HeatConduction + FILES HeatConduction.cpp + DEPENDS core mesa_pd vtk ) diff --git a/apps/showcases/HeatConduction/ContactDetection.h b/apps/showcases/HeatConduction/ContactDetection.h new file mode 100644 index 0000000000000000000000000000000000000000..c5ed90565ea564ef350e1ff5a1931010bb22641a --- /dev/null +++ b/apps/showcases/HeatConduction/ContactDetection.h @@ -0,0 +1,106 @@ +//====================================================================================================================== +// +// 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 ContactDetection.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/collision_detection/AnalyticContactDetection.h> +#include <mesa_pd/collision_detection/AnalyticCollisionFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/shape/BaseShape.h> +#include <mesa_pd/data/shape/HalfSpace.h> +#include <mesa_pd/data/shape/Sphere.h> + +#include <core/logging/Logging.h> + +namespace walberla { +namespace mesa_pd { + +class ContactDetection : public collision_detection::AnalyticContactDetection +{ +public: + ///import all collision detection functions from AnalyticContactDetection + using AnalyticContactDetection::operator(); + + ///overwrite functions that should be different + template <typename Accessor> + bool operator()( const size_t idx1, + const size_t idx2, + const data::Sphere& geo1, + const data::Sphere& geo2, + Accessor& ac); + + template <typename Accessor> + bool operator()( const size_t idx1, + const size_t idx2, + const data::Sphere& s, + const data::HalfSpace& p, + Accessor& ac ); +}; + +template <typename Accessor> +inline bool ContactDetection::operator()( const size_t idx1, + const size_t idx2, + const data::Sphere& geo1, + const data::Sphere& geo2, + Accessor& ac) +{ + using namespace collision_detection::analytic; + WALBERLA_ASSERT_UNEQUAL(idx1, idx2, "colliding with itself!"); + + //ensure collision order idx2 has to be larger than idx1 + if (ac.getUid(idx2) < ac.getUid(idx1)) + return operator()(idx2, idx1, geo2, geo1, ac); + + getIdx1() = idx1; + getIdx2() = idx2; + return detectSphereSphereCollision(ac.getPosition(getIdx1()), + ac.getRadiusAtTemperature(getIdx1()), + ac.getPosition(getIdx2()), + ac.getRadiusAtTemperature(getIdx2()), + getContactPoint(), + getContactNormal(), + getPenetrationDepth(), + getContactThreshold()); +} + +template <typename Accessor> +inline bool ContactDetection::operator()( const size_t idx1, + const size_t idx2, + const data::Sphere& s, + const data::HalfSpace& p, + Accessor& ac ) +{ + using namespace collision_detection::analytic; + WALBERLA_ASSERT_UNEQUAL(idx1, idx2, "colliding with itself!"); + + getIdx1() = idx1; + getIdx2() = idx2; + return detectSphereHalfSpaceCollision(ac.getPosition(getIdx1()), + ac.getRadiusAtTemperature(getIdx1()), + ac.getPosition(getIdx2()), + p.getNormal(), + getContactPoint(), + getContactNormal(), + getPenetrationDepth(), + getContactThreshold()); +} + +} //namespace mesa_pd +} //namespace walberla diff --git a/apps/showcases/HeatConduction/HeatConduction.cfg b/apps/showcases/HeatConduction/HeatConduction.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7d1d729826e3f7e72297c9b009663122afd8ff9b --- /dev/null +++ b/apps/showcases/HeatConduction/HeatConduction.cfg @@ -0,0 +1,15 @@ +HeatConduction +{ + simulationCorner < 0, 0, 0 >; + simulationDomain < 0.3, 0.3, 0.3 >; + blocks < 3,3,1 >; + isPeriodic < 1, 1, 0 >; + + radius 0.004; + spacing 0.010; + vMax 0.00000001; + + dt 0.000001; + simulationSteps 30000; + visSpacing 100; +} diff --git a/apps/showcases/HeatConduction/HeatConduction.cpp b/apps/showcases/HeatConduction/HeatConduction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eea1b2e726dca851debcbea3da698ff843ca8f82 --- /dev/null +++ b/apps/showcases/HeatConduction/HeatConduction.cpp @@ -0,0 +1,302 @@ +//====================================================================================================================== +// +// 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 HeatConduction.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// This showcase combines a classic spring-dashpot interaction model with heat conduction and linear thermal expansion. +// +// First, a set of spheres is dropped onto a plate. The setup is periodic in horizontal directions. The plate as well +// as the spheres shares the same initial temperature. After the spheres have settled, the plate is heated and cooled +// down in a sinus wave. Through thermal conduction the heat is transported through the pile of spheres. At the same +// time a linear thermal expansion model makes the spheres grow and shrink. The parameters are chosen for a visual +// effect and are far to large for a realistic physical simulation. The evolution of the simulation is written to disk +// as vtk files which can be visualized with paraview. +//====================================================================================================================== + +#include <mesa_pd/vtk/ParticleVtkOutput.h> + +#include <mesa_pd/collision_detection/BroadPhase.h> + +#include <mesa_pd/data/LinkedCells.h> +#include <mesa_pd/data/ParticleAccessorWithShape.h> +#include <mesa_pd/data/ParticleStorage.h> +#include <mesa_pd/data/ShapeStorage.h> + +#include <mesa_pd/domain/BlockForestDomain.h> + +#include <mesa_pd/kernel/DoubleCast.h> +#include <mesa_pd/kernel/ExplicitEulerWithShape.h> +#include <mesa_pd/kernel/HeatConduction.h> +#include <mesa_pd/kernel/InsertParticleIntoLinkedCells.h> +#include <mesa_pd/kernel/SpringDashpot.h> +#include <mesa_pd/kernel/TemperatureIntegration.h> + +#include <mesa_pd/mpi/ContactFilter.h> +#include <mesa_pd/mpi/SyncNextNeighbors.h> +#include <mesa_pd/mpi/ReduceProperty.h> + +#include <mesa_pd/mpi/notifications/ForceTorqueNotification.h> +#include <mesa_pd/mpi/notifications/HeatFluxNotification.h> + +#include "ContactDetection.h" +#include "ThermalExpansion.h" + +#include <blockforest/Initialization.h> +#include <core/Abort.h> +#include <core/Environment.h> +#include <core/math/Random.h> +#include <core/mpi/Reduce.h> +#include <core/grid_generator/SCIterator.h> +#include <core/logging/Logging.h> +#include <core/OpenMP.h> +#include <core/timing/Timer.h> +#include <core/timing/TimingPool.h> +#include <core/waLBerlaBuildInfo.h> +#include <sqlite/SQLite.h> +#include <vtk/VTKOutput.h> + +#include <functional> +#include <memory> +#include <string> +#include <mesa_pd/kernel/ParticleSelector.h> + +namespace walberla { +namespace mesa_pd { + +class CustomParticleAccessor : public data::ParticleAccessorWithShape +{ +public: + CustomParticleAccessor(std::shared_ptr<data::ParticleStorage>& ps, std::shared_ptr<data::ShapeStorage>& ss, const real_t radius273K) + : ParticleAccessorWithShape(ps, ss) + , radius273K_(radius273K) + {} + + real_t getRadius273K(const size_t /*p_idx*/) const {return radius273K_;} +private: + real_t radius273K_; +}; + +auto createPlane( const std::shared_ptr<data::ParticleStorage>& ps, + const std::shared_ptr<data::ShapeStorage>& ss, + const Vec3& pos, + const Vec3& normal) +{ + auto p0 = ps->create(true); + p0->setPosition( pos ); + p0->setShapeID( ss->create<data::HalfSpace>( normal ) ); + p0->setOwner( walberla::mpi::MPIManager::instance()->rank() ); + p0->setType( 0 ); + p0->setTemperature( 273 ); + data::particle_flags::set(p0->getFlagsRef(), data::particle_flags::INFINITE); + data::particle_flags::set(p0->getFlagsRef(), data::particle_flags::FIXED); + data::particle_flags::set(p0->getFlagsRef(), data::particle_flags::NON_COMMUNICATING); + return p0; +} + +int main( int argc, char ** argv ) +{ + using namespace walberla::timing; + + Environment env(argc, argv); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + WALBERLA_LOG_INFO_ON_ROOT( "config file: " << argv[1] ); + WALBERLA_LOG_INFO_ON_ROOT( "waLBerla Revision: " << WALBERLA_GIT_SHA1 ); + + math::seedRandomGenerator( static_cast<unsigned int>(1337 * walberla::mpi::MPIManager::instance()->worldRank()) ); + + WALBERLA_LOG_INFO_ON_ROOT("*** READING CONFIG FILE ***"); + auto cfg = env.config(); + if (cfg == nullptr) WALBERLA_ABORT("No config specified!"); + const Config::BlockHandle mainConf = cfg->getBlock( "HeatConduction" ); + + const real_t spacing = mainConf.getParameter<real_t>("spacing", real_t(1.0) ); + WALBERLA_LOG_INFO_ON_ROOT("spacing: " << spacing); + + const real_t radius = mainConf.getParameter<real_t>("radius", real_t(0.5) ); + WALBERLA_LOG_INFO_ON_ROOT("radius: " << radius); + + const real_t vMax = mainConf.getParameter<real_t>("vMax", real_t(0.5) ); + WALBERLA_LOG_INFO_ON_ROOT("vMax: " << vMax); + + int64_t numOuterIterations = mainConf.getParameter<int64_t>("numOuterIterations", 10 ); + WALBERLA_LOG_INFO_ON_ROOT("numOuterIterations: " << numOuterIterations); + + int64_t simulationSteps = mainConf.getParameter<int64_t>("simulationSteps", 10 ); + WALBERLA_LOG_INFO_ON_ROOT("simulationSteps: " << simulationSteps); + + real_t dt = mainConf.getParameter<real_t>("dt", real_c(0.01) ); + WALBERLA_LOG_INFO_ON_ROOT("dt: " << dt); + + const int visSpacing = mainConf.getParameter<int>("visSpacing", 1000 ); + WALBERLA_LOG_INFO_ON_ROOT("visSpacing: " << visSpacing); + const std::string path = mainConf.getParameter<std::string>("path", "vtk_out" ); + WALBERLA_LOG_INFO_ON_ROOT("path: " << path); + + WALBERLA_LOG_INFO_ON_ROOT("*** BLOCKFOREST ***"); + // create forest + auto forest = blockforest::createBlockForestFromConfig( mainConf ); + if (!forest) + { + WALBERLA_LOG_INFO_ON_ROOT( "No BlockForest created ... exiting!"); + return EXIT_SUCCESS; + } + domain::BlockForestDomain domain(forest); + + auto simulationDomain = forest->getDomain(); + auto localDomain = forest->begin()->getAABB(); + for (auto& blk : *forest) + { + localDomain.merge(blk.getAABB()); + } + + WALBERLA_LOG_INFO_ON_ROOT("*** SETUP - START ***"); + + //init data structures + auto ps = std::make_shared<data::ParticleStorage>(100); + auto ss = std::make_shared<data::ShapeStorage>(); + CustomParticleAccessor accessor(ps, ss, radius); + data::LinkedCells lc(localDomain.getExtended(spacing), spacing+spacing ); + + 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)) + { + WALBERLA_CHECK(iBlk.getAABB().contains(pt)); + + auto p = ps->create(); + p->getPositionRef() = pt; + p->getInteractionRadiusRef() = radius; + p->setLinearVelocity( Vec3(math::realRandom(-vMax, vMax),math::realRandom(-vMax, vMax),math::realRandom(-vMax, vMax)) ); + p->getShapeIDRef() = smallSphere; + p->getOwnerRef() = walberla::mpi::MPIManager::instance()->rank(); + p->getTypeRef() = 0; + p->setTemperature( 273 ); + p->setRadiusAtTemperature(radius); + } + } + int64_t numParticles = int64_c(ps->size()); + walberla::mpi::reduceInplace(numParticles, walberla::mpi::SUM); + WALBERLA_LOG_INFO_ON_ROOT("#particles created: " << numParticles); + + auto plane = createPlane(ps, ss, simulationDomain.minCorner(), Vec3(0,0,1)); + createPlane(ps, ss, simulationDomain.maxCorner(), Vec3(0,0,-1)); + + WALBERLA_LOG_INFO_ON_ROOT("*** SETUP - END ***"); + + WALBERLA_LOG_INFO_ON_ROOT("*** VTK ***"); + auto vtkDomainOutput = walberla::vtk::createVTKOutput_DomainDecomposition( forest, "domain_partitioning", 1, "vtk", "simulation_step" ); + auto vtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps) ; + auto vtkWriter = walberla::vtk::createVTKOutput_PointData(vtkOutput, "particles", 1, "vtk", "simulation_step", false, false); + vtkOutput->addOutput<data::SelectParticleOwner>("owner"); + vtkOutput->addOutput<data::SelectParticleTemperature>("temperature"); + vtkOutput->addOutput<data::SelectParticleRadiusAtTemperature>("radius"); + vtkOutput->addOutput<data::SelectParticleLinearVelocity>("linVel"); + vtkOutput->setParticleSelector([smallSphere](const data::ParticleStorage::iterator& pIt){ return pIt->getShapeID() == smallSphere;}); + vtkDomainOutput->write(); + + WALBERLA_LOG_INFO_ON_ROOT("*** SIMULATION - START ***"); + // Init kernels + kernel::ExplicitEuler explicitEuler( dt ); + kernel::InsertParticleIntoLinkedCells ipilc; + kernel::HeatConduction heatConduction(1); + heatConduction.setConductance(0, 0, real_t(1)); + kernel::SpringDashpot dem(1); + dem.setStiffness(0, 0, real_t(8.11e6)); + dem.setDampingN (0, 0, real_t(6.86e1)); + dem.setDampingT (0, 0, real_t(6.86e1)); + dem.setFriction (0, 0, real_t(1.2)); + kernel::TemperatureIntegration temperatureIntegration(dt, 1); + temperatureIntegration.setInvSpecificHeat(0, real_t(0.05) / dt / ss->shapes[smallSphere]->getInvMass()); + kernel::ThermalExpansion thermalExpansion(1); + thermalExpansion.setLinearExpansionCoefficient(0, real_t(0.0005)); + + ContactDetection acd; + kernel::DoubleCast double_cast; + mpi::ContactFilter contact_filter; + mpi::ReduceProperty RP; + mpi::SyncNextNeighbors SNN; + + // initial sync + SNN(*ps, domain); + + for (int64_t i=0; i < simulationSteps; ++i) + { + if (i % visSpacing == 0) + { + vtkWriter->write(); + } + + if (i > visSpacing * 100) + { + auto rad = (real_t(i) - real_t(10000)) * real_t(5e-5) * math::pi; + plane->setTemperature(real_t(273) + real_t(300) * std::sin(rad)); + } + + ps->forEachParticle(false, kernel::SelectMaster(), accessor, [&](const size_t idx, auto& ac){ac.setForce(idx, Vec3(0,0,real_t(-9.81) ) );}, accessor); + + lc.clear(); + ps->forEachParticle(true, kernel::SelectAll(), accessor, ipilc, accessor, lc); + + lc.forEachParticlePairHalf(true, kernel::SelectAll(), accessor, + [&](const size_t idx1, const size_t idx2, auto& ac) + { + if (collision_detection::isInInteractionDistance(idx1, idx2, ac)) + { + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), domain)) + { + dem(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), acd.getContactNormal(), acd.getPenetrationDepth()); + heatConduction(acd.getIdx1(), acd.getIdx2(), ac); + } + } + } + }, + accessor ); + + RP.operator()<ForceTorqueNotification>(*ps); + + RP.operator()<HeatFluxNotification>(*ps); + + ps->forEachParticle(true, kernel::SelectMaster(), accessor, explicitEuler, accessor); + + ps->forEachParticle(true, kernel::SelectMaster(), accessor, temperatureIntegration, accessor); + + if( i % 10 == 0 ) + { + ps->forEachParticle(true, kernel::SelectMaster(), accessor, thermalExpansion, accessor); + } + + SNN(*ps, domain); + } + WALBERLA_LOG_INFO_ON_ROOT("*** SIMULATION - END ***"); + + 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/showcases/HeatConduction/ThermalExpansion.h b/apps/showcases/HeatConduction/ThermalExpansion.h new file mode 100644 index 0000000000000000000000000000000000000000..c56ee0732258220a0b8e67edbaaeb519843d2db3 --- /dev/null +++ b/apps/showcases/HeatConduction/ThermalExpansion.h @@ -0,0 +1,84 @@ +//====================================================================================================================== +// +// 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 ThermalExpansion.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +namespace walberla { +namespace mesa_pd { +namespace kernel { + +class ThermalExpansion +{ +public: + ThermalExpansion(const uint_t numParticleTypes); + ThermalExpansion(const ThermalExpansion& other) = default; + ThermalExpansion(ThermalExpansion&& other) = default; + ThermalExpansion& operator=(const ThermalExpansion& other) = default; + ThermalExpansion& operator=(ThermalExpansion&& other) = default; + + void setLinearExpansionCoefficient(const size_t type, const real_t& val); + real_t getLinearExpansionCoefficient(const size_t type) const; + + template <typename Accessor> + void operator()(const size_t p_idx, Accessor& ac) const; +private: + uint_t numParticleTypes_; + + std::vector<real_t> linearExpansionCoefficient_ {}; +}; + +ThermalExpansion::ThermalExpansion(const uint_t numParticleTypes) +{ + numParticleTypes_ = numParticleTypes; + + linearExpansionCoefficient_.resize(numParticleTypes, real_t(0)); +} + + +inline void ThermalExpansion::setLinearExpansionCoefficient(const size_t type, const real_t& val) +{ + WALBERLA_ASSERT_LESS( type, numParticleTypes_ ); + linearExpansionCoefficient_[type] = val; +} + + +inline real_t ThermalExpansion::getLinearExpansionCoefficient(const size_t type) const +{ + WALBERLA_ASSERT_LESS( type, numParticleTypes_ ); + return linearExpansionCoefficient_[type]; +} + +template <typename Accessor> +inline void ThermalExpansion::operator()(const size_t p_idx, + Accessor& ac) const +{ + static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); + + const auto Tc = ac.getTemperature(p_idx)-real_t(273); + ac.setRadiusAtTemperature(p_idx, ac.getRadius273K(p_idx) * (real_t(1) + Tc * getLinearExpansionCoefficient(ac.getType(p_idx)))); + ac.setInteractionRadius(p_idx, ac.getRadiusAtTemperature(p_idx)); +} + +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla diff --git a/python/mesa_pd.py b/python/mesa_pd.py index 785d9a4ff67129ae687343d8dc00a54a86796b19..a6d7fa151dbde6177ae28c2324fff3e2d6ae93ef 100755 --- a/python/mesa_pd.py +++ b/python/mesa_pd.py @@ -28,6 +28,8 @@ if __name__ == '__main__': ps.add_property("torque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") ps.add_property("oldTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") + ps.add_property("radiusAtTemperature", "walberla::real_t", defValue="real_t(0)", syncMode="ALWAYS") + ps.add_include("blockforest/BlockForest.h") ps.add_property("currentBlock", "blockforest::BlockID", defValue="", syncMode="NEVER") diff --git a/python/mesa_pd/kernel/TemperatureIntegration.py b/python/mesa_pd/kernel/TemperatureIntegration.py index 426a9b3874805db5abac7b686baf791d0a46263a..006eb37232df257eb42c5ac2c7d8be1c44ce72ab 100644 --- a/python/mesa_pd/kernel/TemperatureIntegration.py +++ b/python/mesa_pd/kernel/TemperatureIntegration.py @@ -9,11 +9,12 @@ class TemperatureIntegration: self.context = {'interface': []} self.context['interface'].append(create_access("temperature", "walberla::real_t", access="gs")) self.context['interface'].append(create_access("heatFlux", "walberla::real_t", access="gs")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) self.context['interface'].append(create_access("type", "uint_t", access="g")) def generate(self, module): ctx = {'module': module, **self.context} - ctx["parameters"] = ["invHeatCapacity"] + ctx["parameters"] = ["invSpecificHeat"] generate_file(module['module_path'], 'kernel/TemperatureIntegration.templ.h', ctx) ctx["InterfaceTestName"] = "TemperatureIntegrationInterfaceCheck" diff --git a/python/mesa_pd/templates/kernel/HeatConduction.templ.h b/python/mesa_pd/templates/kernel/HeatConduction.templ.h index 8fe94e6da8e0681556ca441617909f44a6c47d5e..ef12443d9e070444ef050ec77df4c8bc5b2a95ba 100644 --- a/python/mesa_pd/templates/kernel/HeatConduction.templ.h +++ b/python/mesa_pd/templates/kernel/HeatConduction.templ.h @@ -38,9 +38,9 @@ namespace mesa_pd { namespace kernel { /** - * Basic DEM kernel + * Heat conduction interaction kernel * - * This DEM kernel supports spring&dashpot in normal direction as well as friction in tangential direction. + * This kernel implements a simple heat conduction: \frac{dQ}{dt} = - \alpha (T_2 - T_1) * * \code {%- for prop in interface %} diff --git a/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h b/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h index 92aa9f58d9759cf41d4bb708c38b1f4114f025fd..2bdd7f362e6412830c55f78b2f233505ddfc472e 100644 --- a/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h +++ b/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h @@ -34,8 +34,8 @@ namespace mesa_pd { namespace kernel { /** - * Kernel which explicitly integrates all particles in time. - * This integrator integrates velocity and position. + * Kernel which explicitly integrates a particle in time. + * The heat flux is converted into a temperature change. * * This kernel requires the following particle accessor interface * \code @@ -53,8 +53,8 @@ namespace kernel { {%- endfor %} * \endcode * - * \pre All forces acting on the particles have to be set. - * \post All forces are reset to 0. + * \pre Heat flux has to be set/reduced. + * \post Heat flux is reset to 0. * \ingroup mesa_pd_kernel */ class TemperatureIntegration @@ -112,14 +112,14 @@ inline real_t TemperatureIntegration::get{{param | capFirst}}(const size_t type) {%- endfor %} template <typename Accessor> -inline void TemperatureIntegration::operator()(const size_t idx, +inline void TemperatureIntegration::operator()(const size_t p_idx, Accessor& ac) const { static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); //formula for heat capacity - ac.setTemperature(idx, getInvHeatCapacity(ac.getType(idx)) * ac.getHeatFlux(idx) * dt_ + ac.getTemperature(idx)); - ac.setHeatFlux (idx, real_t(0)); + ac.setTemperature(p_idx, getInvSpecificHeat(ac.getType(p_idx)) * ac.getInvMass(p_idx) * ac.getHeatFlux(p_idx) * dt_ + ac.getTemperature(p_idx)); + ac.setHeatFlux (p_idx, real_t(0)); } } //namespace kernel diff --git a/src/mesa_pd/data/ParticleAccessor.h b/src/mesa_pd/data/ParticleAccessor.h index 59e5753306256ae967be958c297696804fd3a0c7..a00eb26c3bc6770288e31a978abaebdcc7f73f2e 100644 --- a/src/mesa_pd/data/ParticleAccessor.h +++ b/src/mesa_pd/data/ParticleAccessor.h @@ -108,6 +108,10 @@ public: walberla::mesa_pd::Vec3& getOldTorqueRef(const size_t p_idx) {return ps_->getOldTorqueRef(p_idx);} void setOldTorque(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setOldTorque(p_idx, v);} + walberla::real_t const & getRadiusAtTemperature(const size_t p_idx) const {return ps_->getRadiusAtTemperature(p_idx);} + walberla::real_t& getRadiusAtTemperatureRef(const size_t p_idx) {return ps_->getRadiusAtTemperatureRef(p_idx);} + void setRadiusAtTemperature(const size_t p_idx, walberla::real_t const & v) { ps_->setRadiusAtTemperature(p_idx, v);} + blockforest::BlockID const & getCurrentBlock(const size_t p_idx) const {return ps_->getCurrentBlock(p_idx);} blockforest::BlockID& getCurrentBlockRef(const size_t p_idx) {return ps_->getCurrentBlockRef(p_idx);} void setCurrentBlock(const size_t p_idx, blockforest::BlockID const & v) { ps_->setCurrentBlock(p_idx, v);} @@ -269,6 +273,10 @@ public: void setOldTorque(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { oldTorque_ = v;} walberla::mesa_pd::Vec3& getOldTorqueRef(const size_t /*p_idx*/) {return oldTorque_;} + walberla::real_t const & getRadiusAtTemperature(const size_t /*p_idx*/) const {return radiusAtTemperature_;} + void setRadiusAtTemperature(const size_t /*p_idx*/, walberla::real_t const & v) { radiusAtTemperature_ = v;} + walberla::real_t& getRadiusAtTemperatureRef(const size_t /*p_idx*/) {return radiusAtTemperature_;} + blockforest::BlockID const & getCurrentBlock(const size_t /*p_idx*/) const {return currentBlock_;} void setCurrentBlock(const size_t /*p_idx*/, blockforest::BlockID const & v) { currentBlock_ = v;} blockforest::BlockID& getCurrentBlockRef(const size_t /*p_idx*/) {return currentBlock_;} @@ -351,6 +359,7 @@ private: walberla::mesa_pd::Vec3 angularVelocity_; walberla::mesa_pd::Vec3 torque_; walberla::mesa_pd::Vec3 oldTorque_; + walberla::real_t radiusAtTemperature_; blockforest::BlockID currentBlock_; uint_t type_; int nextParticle_; diff --git a/src/mesa_pd/data/ParticleStorage.h b/src/mesa_pd/data/ParticleStorage.h index a22470d675486c78bfa154765b33bd197d0a97b2..8e248aca12c376fbf214481a7f9c552ffd5ccfcc 100644 --- a/src/mesa_pd/data/ParticleStorage.h +++ b/src/mesa_pd/data/ParticleStorage.h @@ -86,6 +86,7 @@ public: using angularVelocity_type = walberla::mesa_pd::Vec3; using torque_type = walberla::mesa_pd::Vec3; using oldTorque_type = walberla::mesa_pd::Vec3; + using radiusAtTemperature_type = walberla::real_t; using currentBlock_type = blockforest::BlockID; using type_type = uint_t; using nextParticle_type = int; @@ -162,6 +163,10 @@ public: oldTorque_type& getOldTorqueRef() {return storage_.getOldTorqueRef(i_);} void setOldTorque(oldTorque_type const & v) { storage_.setOldTorque(i_, v);} + radiusAtTemperature_type const & getRadiusAtTemperature() const {return storage_.getRadiusAtTemperature(i_);} + radiusAtTemperature_type& getRadiusAtTemperatureRef() {return storage_.getRadiusAtTemperatureRef(i_);} + void setRadiusAtTemperature(radiusAtTemperature_type const & v) { storage_.setRadiusAtTemperature(i_, v);} + currentBlock_type const & getCurrentBlock() const {return storage_.getCurrentBlock(i_);} currentBlock_type& getCurrentBlockRef() {return storage_.getCurrentBlockRef(i_);} void setCurrentBlock(currentBlock_type const & v) { storage_.setCurrentBlock(i_, v);} @@ -293,6 +298,7 @@ public: using angularVelocity_type = walberla::mesa_pd::Vec3; using torque_type = walberla::mesa_pd::Vec3; using oldTorque_type = walberla::mesa_pd::Vec3; + using radiusAtTemperature_type = walberla::real_t; using currentBlock_type = blockforest::BlockID; using type_type = uint_t; using nextParticle_type = int; @@ -369,6 +375,10 @@ public: oldTorque_type& getOldTorqueRef(const size_t idx) {return oldTorque_[idx];} void setOldTorque(const size_t idx, oldTorque_type const & v) { oldTorque_[idx] = v; } + radiusAtTemperature_type const & getRadiusAtTemperature(const size_t idx) const {return radiusAtTemperature_[idx];} + radiusAtTemperature_type& getRadiusAtTemperatureRef(const size_t idx) {return radiusAtTemperature_[idx];} + void setRadiusAtTemperature(const size_t idx, radiusAtTemperature_type const & v) { radiusAtTemperature_[idx] = v; } + currentBlock_type const & getCurrentBlock(const size_t idx) const {return currentBlock_[idx];} currentBlock_type& getCurrentBlockRef(const size_t idx) {return currentBlock_[idx];} void setCurrentBlock(const size_t idx, currentBlock_type const & v) { currentBlock_[idx] = v; } @@ -531,6 +541,7 @@ public: std::vector<angularVelocity_type> angularVelocity_ {}; std::vector<torque_type> torque_ {}; std::vector<oldTorque_type> oldTorque_ {}; + std::vector<radiusAtTemperature_type> radiusAtTemperature_ {}; std::vector<currentBlock_type> currentBlock_ {}; std::vector<type_type> type_ {}; std::vector<nextParticle_type> nextParticle_ {}; @@ -569,6 +580,7 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(const ParticleSt getAngularVelocityRef() = rhs.getAngularVelocity(); getTorqueRef() = rhs.getTorque(); getOldTorqueRef() = rhs.getOldTorque(); + getRadiusAtTemperatureRef() = rhs.getRadiusAtTemperature(); getCurrentBlockRef() = rhs.getCurrentBlock(); getTypeRef() = rhs.getType(); getNextParticleRef() = rhs.getNextParticle(); @@ -604,6 +616,7 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(ParticleStorage: getAngularVelocityRef() = std::move(rhs.getAngularVelocityRef()); getTorqueRef() = std::move(rhs.getTorqueRef()); getOldTorqueRef() = std::move(rhs.getOldTorqueRef()); + getRadiusAtTemperatureRef() = std::move(rhs.getRadiusAtTemperatureRef()); getCurrentBlockRef() = std::move(rhs.getCurrentBlockRef()); getTypeRef() = std::move(rhs.getTypeRef()); getNextParticleRef() = std::move(rhs.getNextParticleRef()); @@ -640,6 +653,7 @@ void swap(ParticleStorage::Particle lhs, ParticleStorage::Particle rhs) std::swap(lhs.getAngularVelocityRef(), rhs.getAngularVelocityRef()); std::swap(lhs.getTorqueRef(), rhs.getTorqueRef()); std::swap(lhs.getOldTorqueRef(), rhs.getOldTorqueRef()); + std::swap(lhs.getRadiusAtTemperatureRef(), rhs.getRadiusAtTemperatureRef()); std::swap(lhs.getCurrentBlockRef(), rhs.getCurrentBlockRef()); std::swap(lhs.getTypeRef(), rhs.getTypeRef()); std::swap(lhs.getNextParticleRef(), rhs.getNextParticleRef()); @@ -676,6 +690,7 @@ std::ostream& operator<<( std::ostream& os, const ParticleStorage::Particle& p ) "angularVelocity : " << p.getAngularVelocity() << "\n" << "torque : " << p.getTorque() << "\n" << "oldTorque : " << p.getOldTorque() << "\n" << + "radiusAtTemperature : " << p.getRadiusAtTemperature() << "\n" << "currentBlock : " << p.getCurrentBlock() << "\n" << "type : " << p.getType() << "\n" << "nextParticle : " << p.getNextParticle() << "\n" << @@ -782,6 +797,7 @@ inline ParticleStorage::iterator ParticleStorage::create(const id_t& uid) angularVelocity_.emplace_back(real_t(0)); torque_.emplace_back(real_t(0)); oldTorque_.emplace_back(real_t(0)); + radiusAtTemperature_.emplace_back(real_t(0)); currentBlock_.emplace_back(); type_.emplace_back(0); nextParticle_.emplace_back(-1); @@ -843,6 +859,7 @@ inline ParticleStorage::iterator ParticleStorage::erase(iterator& it) angularVelocity_.pop_back(); torque_.pop_back(); oldTorque_.pop_back(); + radiusAtTemperature_.pop_back(); currentBlock_.pop_back(); type_.pop_back(); nextParticle_.pop_back(); @@ -891,6 +908,7 @@ inline void ParticleStorage::reserve(const size_t size) angularVelocity_.reserve(size); torque_.reserve(size); oldTorque_.reserve(size); + radiusAtTemperature_.reserve(size); currentBlock_.reserve(size); type_.reserve(size); nextParticle_.reserve(size); @@ -924,6 +942,7 @@ inline void ParticleStorage::clear() angularVelocity_.clear(); torque_.clear(); oldTorque_.clear(); + radiusAtTemperature_.clear(); currentBlock_.clear(); type_.clear(); nextParticle_.clear(); @@ -958,6 +977,7 @@ inline size_t ParticleStorage::size() const //WALBERLA_ASSERT_EQUAL( uid_.size(), angularVelocity.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), torque.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), oldTorque.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), radiusAtTemperature.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), currentBlock.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), type.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), nextParticle.size() ); @@ -1291,6 +1311,15 @@ public: walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getOldTorque();} }; ///Predicate that selects a certain property from a Particle +class SelectParticleRadiusAtTemperature +{ +public: + using return_type = walberla::real_t; + walberla::real_t& operator()(data::Particle& p) const {return p.getRadiusAtTemperatureRef();} + walberla::real_t& operator()(data::Particle&& p) const {return p.getRadiusAtTemperatureRef();} + walberla::real_t const & operator()(const data::Particle& p) const {return p.getRadiusAtTemperature();} +}; +///Predicate that selects a certain property from a Particle class SelectParticleCurrentBlock { public: diff --git a/src/mesa_pd/kernel/HeatConduction.h b/src/mesa_pd/kernel/HeatConduction.h index 12826c523265f3fd53be7b0ab96661a6ae3cfd0c..57e60cbccb272452e51490cbc5cfd0a35c66840f 100644 --- a/src/mesa_pd/kernel/HeatConduction.h +++ b/src/mesa_pd/kernel/HeatConduction.h @@ -38,9 +38,9 @@ namespace mesa_pd { namespace kernel { /** - * Basic DEM kernel + * Heat conduction interaction kernel * - * This DEM kernel supports spring&dashpot in normal direction as well as friction in tangential direction. + * This kernel implements a simple heat conduction: \frac{dQ}{dt} = - \alpha (T_2 - T_1) * * \code * const walberla::real_t& getTemperature(const size_t p_idx) const; diff --git a/src/mesa_pd/kernel/TemperatureIntegration.h b/src/mesa_pd/kernel/TemperatureIntegration.h index bdfc5732d622164fc05658cb1d30c35285fdd5e8..c90eb3ffcf3b65bb97e77a31d127eb43a02830a9 100644 --- a/src/mesa_pd/kernel/TemperatureIntegration.h +++ b/src/mesa_pd/kernel/TemperatureIntegration.h @@ -34,8 +34,8 @@ namespace mesa_pd { namespace kernel { /** - * Kernel which explicitly integrates all particles in time. - * This integrator integrates velocity and position. + * Kernel which explicitly integrates a particle in time. + * The heat flux is converted into a temperature change. * * This kernel requires the following particle accessor interface * \code @@ -45,12 +45,14 @@ namespace kernel { * const walberla::real_t& getHeatFlux(const size_t p_idx) const; * void setHeatFlux(const size_t p_idx, const walberla::real_t& v); * + * const walberla::real_t& getInvMass(const size_t p_idx) const; + * * const uint_t& getType(const size_t p_idx) const; * * \endcode * - * \pre All forces acting on the particles have to be set. - * \post All forces are reset to 0. + * \pre Heat flux has to be set/reduced. + * \post Heat flux is reset to 0. * \ingroup mesa_pd_kernel */ class TemperatureIntegration @@ -67,16 +69,16 @@ public: /// assumes this parameter is symmetric - void setInvHeatCapacity(const size_t type, const real_t& val); + void setInvSpecificHeat(const size_t type, const real_t& val); - real_t getInvHeatCapacity(const size_t type) const; + real_t getInvSpecificHeat(const size_t type) const; private: real_t dt_ = real_t(0.0); uint_t numParticleTypes_; - std::vector<real_t> invHeatCapacity_ {}; + std::vector<real_t> invSpecificHeat_ {}; }; TemperatureIntegration::TemperatureIntegration(const real_t dt, const uint_t numParticleTypes) @@ -84,32 +86,32 @@ TemperatureIntegration::TemperatureIntegration(const real_t dt, const uint_t num { numParticleTypes_ = numParticleTypes; - invHeatCapacity_.resize(numParticleTypes, real_t(0)); + invSpecificHeat_.resize(numParticleTypes, real_t(0)); } -inline void TemperatureIntegration::setInvHeatCapacity(const size_t type, const real_t& val) +inline void TemperatureIntegration::setInvSpecificHeat(const size_t type, const real_t& val) { WALBERLA_ASSERT_LESS( type, numParticleTypes_ ); - invHeatCapacity_[type] = val; + invSpecificHeat_[type] = val; } -inline real_t TemperatureIntegration::getInvHeatCapacity(const size_t type) const +inline real_t TemperatureIntegration::getInvSpecificHeat(const size_t type) const { WALBERLA_ASSERT_LESS( type, numParticleTypes_ ); - return invHeatCapacity_[type]; + return invSpecificHeat_[type]; } template <typename Accessor> -inline void TemperatureIntegration::operator()(const size_t idx, +inline void TemperatureIntegration::operator()(const size_t p_idx, Accessor& ac) const { static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); //formula for heat capacity - ac.setTemperature(idx, getInvHeatCapacity(ac.getType(idx)) * ac.getHeatFlux(idx) * dt_ + ac.getTemperature(idx)); - ac.setHeatFlux (idx, real_t(0)); + ac.setTemperature(p_idx, getInvSpecificHeat(ac.getType(p_idx)) * ac.getInvMass(p_idx) * ac.getHeatFlux(p_idx) * dt_ + ac.getTemperature(p_idx)); + ac.setHeatFlux (p_idx, real_t(0)); } } //namespace kernel diff --git a/src/mesa_pd/mpi/notifications/ParseMessage.h b/src/mesa_pd/mpi/notifications/ParseMessage.h index 63aa0d542f4d969e6659e64507fb3119335c5473..caf0e0f890312b7566ffd92cd3194728fb09f095 100644 --- a/src/mesa_pd/mpi/notifications/ParseMessage.h +++ b/src/mesa_pd/mpi/notifications/ParseMessage.h @@ -117,6 +117,7 @@ void ParseMessage::operator()(int sender, pIt->setLinearVelocity(objparam.linearVelocity); pIt->setRotation(objparam.rotation); pIt->setAngularVelocity(objparam.angularVelocity); + pIt->setRadiusAtTemperature(objparam.radiusAtTemperature); pIt->setOldContactHistory(objparam.oldContactHistory); pIt->setTemperature(objparam.temperature); diff --git a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h index 2ac5383c17fdda618019c338ef36f47437da1cbf..b01a4dbeb92514fbed8eebcbbc54c6ce92b2f89e 100644 --- a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h @@ -61,6 +61,7 @@ public: walberla::mesa_pd::Rot3 rotation {}; walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; walberla::mesa_pd::Vec3 oldTorque {real_t(0)}; + walberla::real_t radiusAtTemperature {real_t(0)}; uint_t type {0}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; @@ -92,6 +93,7 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setRotation(data.rotation); pIt->setAngularVelocity(data.angularVelocity); pIt->setOldTorque(data.oldTorque); + pIt->setRadiusAtTemperature(data.radiusAtTemperature); pIt->setType(data.type); pIt->setOldContactHistory(data.oldContactHistory); pIt->setTemperature(data.temperature); @@ -138,6 +140,7 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getRotation(); buf << obj.particle_.getAngularVelocity(); buf << obj.particle_.getOldTorque(); + buf << obj.particle_.getRadiusAtTemperature(); buf << obj.particle_.getType(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); @@ -165,6 +168,7 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.rotation; buf >> objparam.angularVelocity; buf >> objparam.oldTorque; + buf >> objparam.radiusAtTemperature; buf >> objparam.type; buf >> objparam.oldContactHistory; buf >> objparam.temperature; diff --git a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h index ca769b85c986a66b3193b74570a80f1de32ce1c9..c4e1c2417b0ca1f02d1b7cbaabd193234085a605 100644 --- a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h @@ -58,6 +58,7 @@ public: size_t shapeID {}; walberla::mesa_pd::Rot3 rotation {}; walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; + walberla::real_t radiusAtTemperature {real_t(0)}; uint_t type {0}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; @@ -82,6 +83,7 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setShapeID(data.shapeID); pIt->setRotation(data.rotation); pIt->setAngularVelocity(data.angularVelocity); + pIt->setRadiusAtTemperature(data.radiusAtTemperature); pIt->setType(data.type); pIt->setOldContactHistory(data.oldContactHistory); pIt->setTemperature(data.temperature); @@ -121,6 +123,7 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getShapeID(); buf << obj.particle_.getRotation(); buf << obj.particle_.getAngularVelocity(); + buf << obj.particle_.getRadiusAtTemperature(); buf << obj.particle_.getType(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); @@ -141,6 +144,7 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.shapeID; buf >> objparam.rotation; buf >> objparam.angularVelocity; + buf >> objparam.radiusAtTemperature; buf >> objparam.type; buf >> objparam.oldContactHistory; buf >> objparam.temperature; diff --git a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h index 62d0c6da38b6d57cee8279b2297d4979824b8d41..d845082000b48affcd17cbfecb77247a6d00662d 100644 --- a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h @@ -50,6 +50,7 @@ public: walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; walberla::mesa_pd::Rot3 rotation {}; walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; + walberla::real_t radiusAtTemperature {real_t(0)}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; }; @@ -86,6 +87,7 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getLinearVelocity(); buf << obj.particle_.getRotation(); buf << obj.particle_.getAngularVelocity(); + buf << obj.particle_.getRadiusAtTemperature(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); return buf; @@ -100,6 +102,7 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.linearVelocity; buf >> objparam.rotation; buf >> objparam.angularVelocity; + buf >> objparam.radiusAtTemperature; buf >> objparam.oldContactHistory; buf >> objparam.temperature; return buf; diff --git a/tests/mesa_pd/kernel/TemperatureIntegration.cpp b/tests/mesa_pd/kernel/TemperatureIntegration.cpp index fefa30cadb52420b7714d39a663213b071e9827c..b84fc9cd285400852b837084603c7185f2fbc9ac 100644 --- a/tests/mesa_pd/kernel/TemperatureIntegration.cpp +++ b/tests/mesa_pd/kernel/TemperatureIntegration.cpp @@ -18,13 +18,11 @@ // //====================================================================================================================== -#include <mesa_pd/data/DataTypes.h> #include <mesa_pd/data/ParticleAccessor.h> #include <mesa_pd/kernel/TemperatureIntegration.h> #include <core/Environment.h> -#include <core/logging/Logging.h> #include <iostream> @@ -45,11 +43,12 @@ int main( int argc, char ** argv ) accessor.setType( 0, 0 ); accessor.setHeatFlux( 0, real_t(8) ); accessor.setTemperature( 0, real_t(5) ); + accessor.setInvMass( 0, real_t(1) ); //init kernels const real_t dt = real_t(1); kernel::TemperatureIntegration integrator( dt, 1 ); - integrator.setInvHeatCapacity( 0, real_t(2) ); + integrator.setInvSpecificHeat( 0, real_t(2) ); integrator(0, accessor); diff --git a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp index e764dffa1b0a1a88b597108d2b64fa6adc4060df..dfc209c39f2d3f6890d1017ab687064d1f7d9deb 100644 --- a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp @@ -44,6 +44,8 @@ public: const walberla::real_t& getHeatFlux(const size_t /*p_idx*/) const {return heatFlux_;} void setHeatFlux(const size_t /*p_idx*/, const walberla::real_t& v) { heatFlux_ = v;} + const walberla::real_t& getInvMass(const size_t /*p_idx*/) const {return invMass_;} + const uint_t& getType(const size_t /*p_idx*/) const {return type_;} @@ -59,6 +61,7 @@ public: private: walberla::real_t temperature_; walberla::real_t heatFlux_; + walberla::real_t invMass_; uint_t type_; };