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 : #include "coupling/filtering/interfaces/FilterInterface.h"
7 : #include <functional>
8 :
9 : namespace coupling {
10 : namespace filtering {
11 : template <unsigned int dim> class FilterFromFunction;
12 : }
13 : } // namespace coupling
14 :
15 : /*
16 : * Extension of FilterInterface.h to allow usage of custom filters using only
17 : * two apply functions. Especially ment to be used for application of filters
18 : * written in Python.
19 : *
20 : * Two std::function pointers are required: One for scalar and one for vector
21 : * processing.
22 : * @author Felix Maurer
23 : */
24 :
25 : template <unsigned int dim> class coupling::filtering::FilterFromFunction : public coupling::filtering::FilterInterface<dim> {
26 : public:
27 0 : FilterFromFunction(
28 : const std::vector<coupling::datastructures::CouplingCell<dim>*>& inputCellVector,
29 : const std::vector<coupling::datastructures::CouplingCell<dim>*>& outputCellVector, std::array<bool, 7> filteredValues,
30 : const std::function<std::vector<double>(std::vector<double>, std::vector<std::array<unsigned int, dim>>)>* applyScalar,
31 : const std::function<std::vector<std::array<double, dim>>(std::vector<std::array<double, dim>>, std::vector<std::array<unsigned int, dim>>)>* applyVector)
32 0 : : coupling::filtering::FilterInterface<dim>(inputCellVector, outputCellVector, filteredValues, "FFF"), _applyScalar(applyScalar),
33 0 : _applyVector(applyVector) {
34 :
35 0 : if (applyScalar == nullptr or applyVector == nullptr)
36 0 : throw std::runtime_error("ERROR: FilterFromFunction received nullptr as function pointer!");
37 :
38 : // cast MaMiCo indexing to std::array
39 0 : tarch::la::Vector<dim, int> mamicoIndex;
40 : std::array<unsigned int, dim> stlIndex;
41 0 : for (unsigned int i = 0; i < inputCellVector.size(); i++) {
42 : // interpret position of cell in inputCellVector as linear local
43 : // md-to-macro index, then convert it to vector
44 : using coupling::indexing::IndexTrait;
45 0 : mamicoIndex = coupling::indexing::convertToVector<dim>(I14{i});
46 :
47 0 : for (unsigned int d = 0; d < dim; d++)
48 0 : stlIndex[d] = mamicoIndex[d];
49 0 : _stlIndices.push_back(stlIndex);
50 : }
51 0 : }
52 :
53 0 : ~FilterFromFunction() {
54 0 : delete _applyScalar;
55 0 : delete _applyVector;
56 0 : }
57 :
58 0 : void operator()() {
59 0 : std::vector<double> input_s;
60 0 : std::vector<std::array<double, dim>> input_v;
61 :
62 0 : input_s.reserve(coupling::filtering::FilterInterface<dim>::_inputCells.size());
63 0 : input_v.reserve(coupling::filtering::FilterInterface<dim>::_inputCells.size());
64 :
65 : /*
66 : * SCALAR
67 : */
68 0 : for (const auto scalarProperty : coupling::filtering::FilterInterface<dim>::_scalarAccessFunctionPairs) {
69 :
70 : /*
71 : * PACK
72 : */
73 0 : for (auto cell : coupling::filtering::FilterInterface<dim>::_inputCells) {
74 0 : input_s.push_back((cell->*scalarProperty.get)());
75 : }
76 :
77 : // std::cout << "Now applying scalar func at: " << _applyScalar <<
78 : // std::endl;
79 : /*
80 : * APPLY
81 : *
82 : * If the cell vector is emtpy, we skip this step. It would not have any
83 : * effect anyway and could cause problems if the apply functions does
84 : * cannot handle empty input sets.
85 : */
86 0 : std::vector<double> output_s = {};
87 0 : if (input_s.size() > 0)
88 0 : output_s = (*_applyScalar)(input_s, _stlIndices);
89 :
90 0 : input_s.clear();
91 :
92 : /*
93 : * UNPACK
94 : */
95 0 : for (unsigned int i = 0; i < coupling::filtering::FilterInterface<dim>::_inputCells.size(); i++) {
96 0 : (coupling::filtering::FilterInterface<dim>::_outputCells[i]->*scalarProperty.set)(output_s[i]);
97 : }
98 : }
99 :
100 : /*
101 : * VECTOR
102 : */
103 0 : for (const auto vectorProperty : coupling::filtering::FilterInterface<dim>::_vectorAccessFunctionPairs) {
104 :
105 : // coupling::FilterInterface<dim>::DEBUG_PRINT_CELL_VELOCITY("FFF BEFORE
106 : // ");
107 :
108 : /*
109 : * PACK
110 : */
111 0 : for (auto cell : coupling::filtering::FilterInterface<dim>::_inputCells) {
112 0 : tarch::la::Vector<dim, double> mamico_vec = (cell->*vectorProperty.get)();
113 : std::array<double, dim> array_vec;
114 0 : for (unsigned int d = 0; d < dim; d++)
115 0 : array_vec[d] = mamico_vec[d];
116 0 : input_v.push_back(array_vec);
117 : }
118 :
119 : // std::cout << "Now applying vector func at: " << _applyVector <<
120 : // std::endl;
121 : /*
122 : * APPLY
123 : *
124 : * Cf. scalar case.
125 : */
126 0 : std::vector<std::array<double, dim>> output_v = {};
127 0 : if (input_v.size() > 0)
128 0 : output_v = (*_applyVector)(input_v, _stlIndices);
129 :
130 0 : input_v.clear();
131 :
132 : /*
133 : * UNPACK
134 : */
135 0 : for (unsigned int i = 0; i < coupling::filtering::FilterInterface<dim>::_inputCells.size(); i++) {
136 0 : tarch::la::Vector<dim, double> mamico_vec{};
137 0 : for (unsigned int d = 0; d < dim; d++)
138 0 : mamico_vec[d] = output_v[i][d];
139 0 : (coupling::filtering::FilterInterface<dim>::_outputCells[i]->*vectorProperty.set)(mamico_vec);
140 : }
141 :
142 : // coupling::FilterInterface<dim>::DEBUG_PRINT_CELL_VELOCITY("FFF AFTER
143 : // ");
144 : }
145 0 : }
146 :
147 : private:
148 : // FFFs use slightly different datastructures for index/cell storage than
149 : // other filters
150 : std::vector<std::array<unsigned int, dim>> _stlIndices;
151 :
152 : // this encodes what filter to use
153 : const std::function<std::vector<double>(std::vector<double>, std::vector<std::array<unsigned int, dim>>)>* _applyScalar;
154 : const std::function<std::vector<std::array<double, dim>>(std::vector<std::array<double, dim>>, std::vector<std::array<unsigned int, dim>>)>* _applyVector;
155 : };
|