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 : };