Line data Source code
1 : // This file is part of the Mamico project. For conditions of distribution
2 : // and use, please see the copyright notice in Mamico's main folder, or at
3 : // www5.in.tum.de/mamico
4 :
5 : #pragma once
6 :
7 : #include <cmath>
8 : #include <string>
9 : #include <vector>
10 :
11 : // #define DEBUG_GAUSS
12 : #include "coupling/filtering/interfaces/FilterInterface.h"
13 :
14 : namespace coupling {
15 : namespace filtering {
16 : template <unsigned int dim, coupling::indexing::IndexTrait... scope> class Gauss;
17 :
18 : // cf. member variable in coupling::Gauss for more details
19 : enum GaussExtrapolationStrategy { NONE, MIRROR, REFLECT };
20 : } // namespace filtering
21 : } // namespace coupling
22 :
23 : // Define kernel radius. e.g. radius = 1 means kernel size of 3
24 : #define GAUSS_KERNEL_RADIUS 1
25 :
26 : /*
27 : * Gaussian filter.
28 : * Operates in one dimension: If you wish to use a multidimensional gaussian
29 : * filter, simply chain multiple instances of this filter in one FilterSequence.
30 : *
31 : * @author Felix Maurer
32 : */
33 : template <unsigned int dim, coupling::indexing::IndexTrait... scope> class coupling::filtering::Gauss : public coupling::filtering::FilterInterface<dim> {
34 : using coupling::filtering::FilterInterface<dim>::_inputCells;
35 : using coupling::filtering::FilterInterface<dim>::_outputCells;
36 : using coupling::filtering::FilterInterface<dim>::_scalarAccessFunctionPairs;
37 : using coupling::filtering::FilterInterface<dim>::_vectorAccessFunctionPairs;
38 :
39 : using ScalarIndex = coupling::indexing::CellIndex<dim, scope..., coupling::indexing::IndexTrait::md2macro, coupling::indexing::IndexTrait::noGhost>;
40 : using VectorIndex = coupling::indexing::CellIndex<dim, coupling::indexing::IndexTrait::vector, scope..., coupling::indexing::IndexTrait::md2macro,
41 : coupling::indexing::IndexTrait::noGhost>;
42 :
43 : public:
44 0 : Gauss(const std::vector<coupling::datastructures::CouplingCell<dim>*>& inputCellVector,
45 : const std::vector<coupling::datastructures::CouplingCell<dim>*>& outputCellVector, const std::array<bool, 7> filteredValues, unsigned int dimension,
46 : int sigma, const char* extrapolationStrategy)
47 0 : : coupling::filtering::FilterInterface<dim>(inputCellVector, outputCellVector, filteredValues, "GAUSS"), _dim(dimension), _sigma(sigma),
48 0 : _kernel(generateKernel()) {
49 : // TODO
50 : if (GAUSS_KERNEL_RADIUS != 1)
51 : throw std::runtime_error("ERROR: GAUSS: Kernel radius != 1 currently not supported.");
52 :
53 0 : if (extrapolationStrategy == nullptr || std::strcmp(extrapolationStrategy, "none") == 0)
54 0 : _extrapolationStrategy = NONE;
55 0 : else if (std::strcmp(extrapolationStrategy, "mirror") == 0)
56 0 : _extrapolationStrategy = MIRROR;
57 0 : else if (std::strcmp(extrapolationStrategy, "reflect") == 0)
58 0 : _extrapolationStrategy = REFLECT;
59 : else {
60 0 : std::cout << "Extrapolation strategy: " << extrapolationStrategy << std::endl;
61 0 : throw std::runtime_error("ERROR: GAUSS: Unknown extrapolation strategy.");
62 : }
63 :
64 : #ifdef DEBUG_GAUSS
65 : std::cout << " GAUSS (Dim: " << _dim << "): Created Gaussian filter." << std::endl;
66 : if (_extrapolationStrategy == NONE)
67 : std::cout << " It will not use extrapolation." << std::endl;
68 : if (_extrapolationStrategy == MIRROR)
69 : std::cout << " It will use mirroring extrapolation." << std::endl;
70 : if (_extrapolationStrategy == REFLECT)
71 : std::cout << " It will use reflecting extrapolation." << std::endl;
72 : #endif
73 0 : }
74 :
75 0 : ~Gauss() {
76 : #ifdef DEBUG_GAUSS
77 : std::cout << " GAUSS (Dim: " << _dim << "): Gaussian filter deconstructed" << std::endl;
78 : #endif
79 0 : }
80 :
81 : void operator()();
82 :
83 : private:
84 : std::array<double, 1 + 2 * GAUSS_KERNEL_RADIUS> generateKernel();
85 :
86 : constexpr double gaussianDensityFunction(int x);
87 :
88 : /*
89 : * Returns the index of the cell cell that's above the cell at index on the
90 : * d-axis If no such index exists, index (the first parameter) is returned.
91 : *
92 : * Index is assumed to be in terms of the MD2Macro domain, i.e. (0,..0) is the
93 : * lowest cell that gets sent from MD to Macro.
94 : */
95 :
96 : VectorIndex getIndexAbove(const VectorIndex index, unsigned int d);
97 :
98 : /*
99 : * Returns the index of the cell that's below the cell at index on the d-axis
100 : * If no such index exists, index (the first parameter) is returned.
101 : *
102 : * Index is assumed to be in terms of the MD2Macro domain, i.e. (0,..0) is the
103 : * lowest cell that gets sent from MD to Macro.
104 : */
105 :
106 : VectorIndex getIndexBelow(const VectorIndex index, unsigned int d);
107 :
108 : // on which axis this filter operates. 0 <= _dim <= dim
109 : const unsigned int _dim;
110 :
111 : // standard deviation used
112 : const double _sigma;
113 :
114 : std::array<double, 1 + 2 * GAUSS_KERNEL_RADIUS> _kernel;
115 :
116 : /**
117 : * Determines how to apply filter to border cells:
118 : * NONE = only use existing cells and normalize their weight accordingly
119 : * MIRROR = b | a b c d | c
120 : * REFLECT = a | a b c d | d
121 : *
122 : * The last two are congruent to SciPy's gaussian filter's respective
123 : * extrapolation modes
124 : */
125 : coupling::filtering::GaussExtrapolationStrategy _extrapolationStrategy;
126 : };
127 :
128 : // include implementation of header
129 : #include "Gauss.cpph"
|