LCOV - code coverage report
Current view: top level - coupling/filtering/sequencing - FilterSequence.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 72 0
Test Date: 2026-08-21 15:14:06 Functions: 0.0 % 12 0

            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 <functional>
       7              : #include <map>
       8              : #include <numeric>
       9              : #include <sys/time.h>
      10              : 
      11              : #include "coupling/filtering/interfaces/FilterInterface.h"
      12              : #include "coupling/indexing/CellIndex.h"
      13              : #include "tarch/configuration/ParseConfiguration.h"
      14              : 
      15              : // INCLUDE ALL FILTER HEADERS HERE
      16              : #include "coupling/filtering/filters/Constant.h"
      17              : #include "coupling/filtering/filters/Gauss.h"
      18              : #ifdef BUILD_WITH_EIGEN
      19              : #include "coupling/filtering/filters/POD.h"
      20              : #endif
      21              : #include "coupling/filtering/filters/ReadFromFile.h"
      22              : #include "coupling/filtering/filters/WriteToFile.h"
      23              : /*
      24              : #include "coupling/filtering/filters/Strouhal.h"
      25              : */
      26              : #include "coupling/filtering/filters/Copy.h"
      27              : #include "coupling/filtering/filters/FilterFromFunction.h"
      28              : 
      29              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      30              : #include "coupling/filtering/SequentialFilter.h"
      31              : #endif
      32              : 
      33              : /*
      34              :  * Filter Sequences are used to group filters that will be applied in
      35              :  * chronological order. It is possible to customize
      36              :  *  - sequence input
      37              :  *      - filter parameters
      38              :  *      - modifiablitiy of filter list
      39              :  * per Filter Sequence.
      40              :  *
      41              :  * A generalized version of this concept is FilterJunction.
      42              :  * @author Felix Maurer
      43              :  */
      44              : 
      45              : namespace coupling {
      46              : namespace filtering {
      47              : template <unsigned int dim> class FilterSequence;
      48              : }
      49              : } // namespace coupling
      50              : 
      51              : template <unsigned int dim> class coupling::filtering::FilterSequence {
      52              : public:
      53              :   /*
      54              :    * Filter Sequences are constructed in
      55              :    * coupling::FilterPipeline::loadSequencesFromXML(...).
      56              :    */
      57            0 :   FilterSequence(const char* name, const std::vector<coupling::datastructures::CouplingCell<dim>*> inputCells,
      58              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      59              :                  MPI_Comm comm,
      60              : #endif
      61              :                  std::array<bool, 7> filteredValues = {true})
      62            0 :       : _name(name), _inputCellVector(inputCells),
      63              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      64            0 :         _comm(comm),
      65              : #endif
      66            0 :         _filteredValues(filteredValues), _isOutput(false), // potentially updated via loadSequencesFromXML
      67              :                                                            // calling setAsOutput()
      68            0 :         _isModifiable(true),                               // TODO: allow const sequences via XML attribute
      69            0 :         _timestepsElapsed(0) {
      70              : #ifdef DEBUG_FILTER_PIPELINE
      71              :     std::cout << PRINT_PREFIX() << "Now initializing." << std::endl;
      72              : #endif
      73              : 
      74            0 :     initCellVectors();
      75              : 
      76            0 :     bool filtersAnything = false;
      77            0 :     for (unsigned int i = 0; i < 7; i++)
      78            0 :       if (_filteredValues[i]) {
      79              :         filtersAnything = true;
      80              :         break;
      81              :       }
      82            0 :     if (!filtersAnything)
      83              :       std::cout << "Warning: Filter sequence " << _name
      84            0 :                 << " does not filter any values. Add 'filtered-values' "
      85              :                    "attribute to XML element to change this."
      86            0 :                 << std::endl;
      87              : #ifdef DEBUG_FILTER_PIPELINE
      88              :     std::cout << PRINT_PREFIX() << "Finished initialization." << std::endl;
      89              : #endif
      90            0 :   }
      91              : 
      92            0 :   virtual ~FilterSequence() {
      93              :     // Output average application times for all filters
      94              : #ifdef DEBUG_FILTER_PIPELINE
      95              :     if (IDXS.getRank() == 0) {
      96              :       std::cout << PRINT_PREFIX() << "Average application times for filters in this sequence in \u03BCs:" << std::endl;
      97              :       for (auto filter : _filters) {
      98              :         std::cout << "       " << filter->getType() << ": "
      99              :                   << (double)std::accumulate(_filterTimes[filter].begin(), _filterTimes[filter].end(), 0) / (double)_timestepsElapsed << std::endl;
     100              :       }
     101              :     }
     102              : #endif
     103              : 
     104            0 :     for (auto v1 : _cellVector1)
     105            0 :       delete v1;
     106            0 :     for (auto v2 : _cellVector2)
     107            0 :       delete v2;
     108            0 :     for (auto f : _filters)
     109            0 :       delete f;
     110              : #ifdef DEBUG_FILTER_PIPELINE
     111              :     std::cout << PRINT_PREFIX() << "Deconstructed." << std::endl;
     112              : #endif
     113            0 :   }
     114              : 
     115              :   /*
     116              :    * Each sequence operates on their own two copies of the md-to-macro domain.
     117              :    * Thus, before applying the sequence, we need to update these two copies.
     118              :    */
     119            0 :   void updateCellVectors() {
     120            0 :     for (unsigned int index = 0; index < _cellVector1.size(); index++) {
     121            0 :       *(_cellVector1[index]) = *(_inputCellVector[index]);
     122            0 :       *(_cellVector2[index]) = *(_inputCellVector[index]);
     123              :     }
     124            0 :   }
     125              : 
     126              :   /*
     127              :    * Applies all filters stored in _filters. Also measures performance times.
     128              :    */
     129            0 :   void operator()() {
     130            0 :     for (auto filter : _filters) {
     131              :       // measure time before application
     132              :       timeval before;
     133            0 :       gettimeofday(&before, NULL);
     134              : 
     135              :       // Apply the filter's operator()
     136            0 :       (*filter)();
     137              : 
     138              :       // measure time after application
     139              :       timeval after;
     140            0 :       gettimeofday(&after, NULL);
     141              : 
     142              :       // store time difference in usec in map
     143            0 :       _filterTimes[filter].push_back((after.tv_sec * 1000000 + after.tv_usec) - (before.tv_sec * 1000000 + before.tv_usec));
     144              : 
     145              : #ifdef DEBUG_FILTER_PIPELINE
     146              :       std::cout << PRINT_PREFIX() << "Applied filter " << filter->getType() << ". Application time: " << _filterTimes[filter].back() << "\u03BCs" << std::endl;
     147              : #endif
     148              :     }
     149            0 :     _timestepsElapsed++;
     150            0 :   }
     151              : 
     152              :   /*
     153              :    * Returns unique name identifier of this sequence.
     154              :    */
     155            0 :   const char* getName() { return _name; }
     156              : 
     157            0 :   bool isOutputToMacro() { return _isOutput; }
     158            0 :   void setAsOutputToMacro() {
     159              : #ifdef DEBUG_FILTER_PIPELINE
     160              :     std::cout << PRINT_PREFIX() << " Setting as pipeline to macro solver output." << std::endl;
     161              : #endif
     162            0 :     _isOutput = true;
     163            0 :   }
     164              : 
     165              :   /*
     166              :    * Modifiable sequences may have filters added dynamically via
     167              :    * FilterFromFunction.
     168              :    */
     169            0 :   bool isModifiable() { return _isModifiable; }
     170            0 :   void makeUnmodifiable() { _isModifiable = false; }
     171              : 
     172              :   std::vector<coupling::filtering::FilterInterface<dim>*> getFilters() { return _filters; }
     173              : 
     174              :   /*
     175              :    * All virtual functions below are redefined in case this sequence is actually
     176              :    * a FilterJunction. Read FilterJunction.h carefully.
     177              :    */
     178              : 
     179              :   /*
     180              :    * Interprets this sequence's filters' parameters (specified in
     181              :    * filter_pipeline.xml) and creates filter objects based on that. Since
     182              :    * different filters require vastly different parameters and thus different
     183              :    * means of instanciation, you need to add each new filter manually to this
     184              :    * method's "if/else-chain".
     185              :    *
     186              :    * Since after all filter objects are created it is possible to determine
     187              :    * whether _cellVector1 or _cellVector2 will be used as output, this is also
     188              :    * done in here.
     189              :    *
     190              :    * In addition to that, if this sequence is declared as unmodifibale, this
     191              :    * gets also detected in here.
     192              :    */
     193              :   virtual int loadFiltersFromXML(tinyxml2::XMLElement* sequenceNode);
     194              : 
     195              :   /*
     196              :    * This member function allows appendance and insertion of filters defined by
     197              :    * two processing functions to a modifiable sequence at runtime. Index -1
     198              :    * implies appending.
     199              :    */
     200              :   virtual void addFilter(
     201              :       const std::function<std::vector<double>(std::vector<double>, std::vector<std::array<unsigned int, dim>>)>* applyScalar,
     202              :       const std::function<std::vector<std::array<double, dim>>(std::vector<std::array<double, dim>>, std::vector<std::array<unsigned int, dim>>)>* applyVector,
     203              :       int filterIndex = -1);
     204              : 
     205              :   /*
     206              :    * Registers existence of a child sequence, i.e. a sequence using this
     207              :    * sequence's output as its input.
     208              :    */
     209            0 :   virtual void addChildSequence(coupling::filtering::FilterSequence<dim>* childSequence) { _childSequences.push_back(childSequence); }
     210              : 
     211              :   /*
     212              :    * Allows changing the input cells after init.
     213              :    */
     214            0 :   virtual void updateInputCellVector(const std::vector<coupling::datastructures::CouplingCell<dim>*> newInputCellVector) {
     215            0 :     _inputCellVector = newInputCellVector; // call copy constructor
     216              : 
     217              :     // cc this change to this sequence's first vector.
     218            0 :     if (!_filters.empty())
     219            0 :       _filters[0]->setInputCells(_inputCellVector);
     220            0 :   }
     221              : 
     222              :   /*
     223              :    * Which one of the two cell vectors are this sequence's output is solely
     224              :    * dependant on the number of filters the sequence contains, because each swap
     225              :    * (see loadFiltersFromXML) changes what is the sequence's final filter's
     226              :    * output.
     227              :    *
     228              :    * Some sequences have more than one output, thus the optional parameter. Has
     229              :    * no effect on a basic FilterSequence.
     230              :    */
     231            0 :   virtual const std::vector<coupling::datastructures::CouplingCell<dim>*>& getOutputCellVector(unsigned int outputIndex = 0) const {
     232            0 :     if (_filters.empty())
     233            0 :       return _inputCellVector;
     234              : 
     235            0 :     if (_filters.size() % 2 == 0)
     236            0 :       return _cellVector1;
     237              : 
     238            0 :     return _cellVector2;
     239              :   }
     240              : 
     241            0 :   virtual void printOutputCellVector() const {
     242            0 :     if (getOutputCellVector() == _inputCellVector)
     243            0 :       std::cout << "The sequence's input cell vector ";
     244            0 :     else if (getOutputCellVector() == _cellVector1)
     245            0 :       std::cout << "Cell vector 1 ";
     246            0 :     else if (getOutputCellVector() == _cellVector2)
     247            0 :       std::cout << "Cell vector 2 ";
     248              :     else { /*unreachable, see function definition above*/
     249              :     }
     250              : 
     251            0 :     std::cout << "will be used as output." << std::endl;
     252            0 :   }
     253              : 
     254              :   /*
     255              :    * This is trivial for the traditional sequence, i.e. non-Junction-case.
     256              :    */
     257            0 :   virtual unsigned int getNumInputs() { return 1; }
     258            0 :   virtual unsigned int getNumOutputs() { return 1; }
     259              : 
     260              :   /*
     261              :    * DUMMY HELPER FUNCTIONS
     262              :    */
     263              : 
     264            0 :   virtual void printFilters() {
     265            0 :     std::cout << "Filters in sequence " << _name << ": ";
     266            0 :     for (auto f : _filters)
     267            0 :       std::cout << f->getType() << " ";
     268            0 :     std::cout << std::endl;
     269            0 :   }
     270              : 
     271            0 :   virtual std::string PRINT_PREFIX() const { return std::string("  FS(").std::string::append(_name).std::string::append("): "); }
     272              : 
     273              : private:
     274              :   /*
     275              :    * Copies all input cells to _cellVector1 and _cellVector2.
     276              :    *
     277              :    * Used in consctructor.
     278              :    *
     279              :    * Not implemented by FilterJunction: Equivalent procedure can be found in
     280              :    * that class' constructor.
     281              :    */
     282              :   void initCellVectors();
     283              : 
     284              : protected:
     285              :   const char* _name;
     286              : 
     287              :   std::vector<coupling::datastructures::CouplingCell<dim>*> _inputCellVector; // points to (foreign) input vector
     288              :   std::vector<coupling::datastructures::CouplingCell<dim>*> _cellVector1;     // allocated for this sequence only
     289              :   std::vector<coupling::datastructures::CouplingCell<dim>*> _cellVector2;     // allocated for this sequence only
     290              : 
     291              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     292              :   MPI_Comm _comm;
     293              : #endif
     294              : 
     295              :   std::array<bool, 7> _filteredValues;
     296              : 
     297              :   bool _isOutput;     // true if this sequence's output vector (see above) is the
     298              :                       // Filter Pipeline's output
     299              :   bool _isModifiable; // true while filters can be added to sequence
     300              : 
     301              :   std::vector<coupling::filtering::FilterInterface<dim>*> _filters;
     302              : 
     303              :   // stores application times for all filters
     304              :   std::map<coupling::filtering::FilterInterface<dim>*, std::vector<unsigned int>> _filterTimes;
     305              : 
     306              :   // there must be some other place to get this from
     307              :   unsigned int _timestepsElapsed;
     308              : 
     309              :   // stores pointers to all sequences that use this sequence's output as their
     310              :   // input.
     311              :   std::vector<coupling::filtering::FilterSequence<dim>*> _childSequences;
     312              : };
     313              : 
     314              : // inlcude implementation
     315              : #include "coupling/filtering/sequencing/FilterSequence.cpph"
        

Generated by: LCOV version 2.0-1