ParticlePresenceLevelDetermination.h 4.62 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//======================================================================================================================
//
//  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 ParticlePresenceLevelDetermination.h
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================

#pragma once

#include "blockforest/BlockForest.h"
#include "lbm_mesapd_coupling/amr/InfoCollection.h"

namespace walberla {
namespace lbm_mesapd_coupling {
28
29
namespace amr
{
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Class to determine the minimum level a block can be.
 * For coupled LBM-PE simulations the following rules apply:
 *  - a moving particle will always remain on the finest block
 *  - a moving particle is not allowed to extend into an area with a coarser block
 *  - if no moving particle is present, the level can be as coarse as possible (restricted by the 2:1 rule)
 * Therefore, if a particle, local or remote (due to particles that are larger than a block), is present on any of the
 * neighboring blocks of a certain block, this block's target level is the finest level.
 * This, together with a refinement checking frequency that depends on the maximum translational particle velocity,
 * ensures the above given requirements.
 */
class ParticlePresenceLevelDetermination
{
43
44
45
46
 public:
   ParticlePresenceLevelDetermination(const shared_ptr< InfoCollection > infoCollection,
                                      uint_t finestLevel)
      : infoCollection_(infoCollection), finestLevel_(finestLevel)
47
48
   {}

49
50
51
52
53
   void operator()(std::vector< std::pair< const Block*, uint_t > >& minTargetLevels, std::vector< const Block* >&,
                   const BlockForest& /*forest*/)
   {
      for (auto& minTargetLevel : minTargetLevels)
      {
54
55
         uint_t currentLevelOfBlock = minTargetLevel.first->getLevel();

56
57
         const uint_t numberOfParticlesInDirectNeighborhood =
            getNumberOfLocalAndShadowParticlesInNeighborhood(minTargetLevel.first);
58

59
60
         uint_t targetLevelOfBlock = currentLevelOfBlock; // keep everything as it is
         if (numberOfParticlesInDirectNeighborhood > uint_t(0))
61
62
63
64
65
66
67
         {
            // set block to finest level if there are particles nearby
            targetLevelOfBlock = finestLevel_;
         }
         else
         {
            // block could coarsen since there are no particles nearby
68
            if (currentLevelOfBlock > uint_t(0)) targetLevelOfBlock = currentLevelOfBlock - uint_t(1);
69
70
         }

71
72
         WALBERLA_CHECK_LESS_EQUAL(std::abs(int_c(targetLevelOfBlock) - int_c(currentLevelOfBlock)), uint_t(1),
                                   "Only level difference of maximum 1 allowed!");
73
74
75
76
         minTargetLevel.second = targetLevelOfBlock;
      }
   }

77
78
79
 private:
   uint_t getNumberOfLocalAndShadowParticlesInNeighborhood(const Block* block)
   {
80
81
82
83
      auto numParticles = uint_t(0);

      // add particles of current block
      const auto infoIt = infoCollection_->find(block->getId());
84
85
      WALBERLA_CHECK_UNEQUAL(infoIt, infoCollection_->end(),
                             "Block with ID " << block->getId() << " not found in info collection!");
86

87
      numParticles += infoIt->second.numberOfLocalParticles + infoIt->second.numberOfGhostParticles;
88
89

      // add particles of all neighboring blocks
90
      for (uint_t i = 0; i < block->getNeighborhoodSize(); ++i)
91
      {
92
93
94
95
         const BlockID& neighborBlockID = block->getNeighborId(i);
         const auto infoItNeighbor      = infoCollection_->find(neighborBlockID);
         WALBERLA_CHECK_UNEQUAL(infoItNeighbor, infoCollection_->end(),
                                "Neighbor block with ID " << neighborBlockID << " not found in info collection!");
96

97
         numParticles += infoItNeighbor->second.numberOfLocalParticles + infoItNeighbor->second.numberOfGhostParticles;
98
99
100
101
      }
      return numParticles;
   }

102
   shared_ptr< InfoCollection > infoCollection_;
103
104
105
   uint_t finestLevel_;
};

106
} // namespace amr
107
108
} // namespace lbm_mesapd_coupling
} // namespace walberla