LCOV - code coverage report
Current view: top level - coupling/filtering/sequencing - FilterSequence.cpph (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 109 0.0 %
Date: 2025-06-25 11:26:37 Functions: 0 3 0.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/mamic::o
       4             : 
       5             : #include <typeinfo>
       6             : 
       7             : // Member functions of coupling::filtering::FilterSequence
       8             : 
       9           0 : template <unsigned int dim> int coupling::filtering::FilterSequence<dim>::loadFiltersFromXML(tinyxml2::XMLElement* sequenceNode) {
      10           0 :   if (!sequenceNode)
      11             :     return EXIT_FAILURE;
      12           0 :   tinyxml2::XMLElement* currFilterNode = sequenceNode->FirstChildElement();
      13             : 
      14           0 :   std::vector<coupling::datastructures::CouplingCell<dim>*> inputCellVector = _inputCellVector;
      15           0 :   std::vector<coupling::datastructures::CouplingCell<dim>*> outputCellVector = _cellVector2;
      16             : 
      17             : #ifdef DEBUG_FILTER_PIPELINE
      18             :   std::cout << PRINT_PREFIX() << "Initializing filter objects." << std::endl;
      19             : #endif
      20             :   bool firstIteration = true;
      21             : 
      22           0 :   while (currFilterNode) {
      23           0 :     coupling::filtering::FilterInterface<dim>* newfilter = nullptr;
      24             : 
      25           0 :     bool sequential = false;
      26           0 :     if (const char* seqAttr = currFilterNode->Attribute("sequential"))
      27           0 :       if (std::strcmp(seqAttr, "true") == 0)
      28           0 :         sequential = true;
      29             : 
      30             :     // ###############################################################
      31             :     //  This is where you have to define how to handle each filter individually.
      32             :     //  Write To File
      33           0 :     if (std::strcmp(currFilterNode->Value(), "write-to-file") == 0) {
      34           0 :       bool overwrite = false;
      35           0 :       if (currFilterNode->Attribute("overwrite"))
      36           0 :         if (std::strcmp(currFilterNode->Attribute("overwrite"), "true") == 0)
      37           0 :           overwrite = true;
      38             : 
      39           0 :       int oco = -1;
      40           0 :       tarch::configuration::ParseConfiguration::readIntOptional(oco, currFilterNode, "one-cell-only");
      41           0 :       if (oco < -1 || oco >= (int)inputCellVector.size()) {
      42           0 :         std::cout << "ERROR: XML config file references undefined cell index " << oco << " for write-to-file." << std::endl;
      43           0 :         exit(EXIT_FAILURE);
      44             :       }
      45             : 
      46           0 :       const std::string location = currFilterNode->Attribute("location");
      47             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      48             :       using namespace std::string_literals;
      49             :       int rank;
      50           0 :       MPI_Comm_rank(_comm, &rank);
      51             : 
      52           0 :       newfilter =
      53           0 :           new coupling::filtering::WriteToFile<dim>(inputCellVector, outputCellVector, _filteredValues, std::to_string(rank) + "_"s + location, overwrite, oco);
      54             : #else
      55             :       newfilter = new coupling::filtering::WriteToFile<dim>(inputCellVector, outputCellVector, _filteredValues, location, overwrite, oco);
      56             : #endif
      57           0 :     }
      58             : 
      59             :     // Read From File
      60           0 :     else if (std::strcmp(currFilterNode->Value(), "read-from-file") == 0) {
      61             : 
      62           0 :       newfilter = new coupling::filtering::ReadFromFile<dim>(inputCellVector, outputCellVector, _filteredValues, currFilterNode->Attribute("location"));
      63           0 :       const std::string location = currFilterNode->Attribute("location");
      64             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      65             :       using namespace std::string_literals;
      66             :       int rank;
      67           0 :       MPI_Comm_rank(_comm, &rank);
      68             : 
      69           0 :       newfilter = new coupling::filtering::ReadFromFile<dim>(inputCellVector, outputCellVector, _filteredValues, std::to_string(rank) + "_"s + location);
      70             : #else
      71             :       newfilter = new coupling::filtering::ReadFromFile<dim>(inputCellVector, outputCellVector, _filteredValues, location);
      72             : #endif
      73             : 
      74           0 :     }
      75             : 
      76             :     // Constant Filter
      77           0 :     else if (std::strcmp(currFilterNode->Value(), "constant") == 0) {
      78           0 :       double constant = 0.0; // by default, constant filter uses 0 as its constant.
      79           0 :       tarch::configuration::ParseConfiguration::readDoubleOptional(constant, currFilterNode, "value");
      80             : 
      81           0 :       tarch::la::Vector<dim, bool> filteredDims = {true}; // default: filter multidimensional properties in all dims
      82           0 :       int dir = -1;
      83           0 :       tarch::configuration::ParseConfiguration::readIntOptional(dir, currFilterNode, "dir");
      84           0 :       if (dir >= 0 && (unsigned int)dir < dim) /*if d is within range...*/ {
      85             :         /*... set all dims but d to false*/
      86           0 :         filteredDims = {false};
      87           0 :         filteredDims[dir] = true;
      88             :       }
      89             : 
      90           0 :       newfilter = new coupling::filtering::Constant<dim>(inputCellVector, outputCellVector, _filteredValues, filteredDims, constant);
      91             :     }
      92             : 
      93             :     // Gauss
      94           0 :     else if (std::strcmp(currFilterNode->Value(), "gauss") == 0) {
      95             :       // dimension the gauss filter operates on
      96             :       int d;
      97           0 :       if (currFilterNode->QueryIntAttribute("dim", &d)) {
      98           0 :         std::cout << "ERROR: Gaussian filter misses attribute dim in config file." << std::endl;
      99           0 :         exit(EXIT_FAILURE);
     100             :       }
     101             : 
     102             :       // standard deviation of the gauss filter
     103             :       double sigma;
     104           0 :       if (currFilterNode->QueryDoubleAttribute("sigma", &sigma)) {
     105           0 :         std::cout << "ERROR: Gaussian filter misses attribute sigma in config file." << std::endl;
     106           0 :         exit(EXIT_FAILURE);
     107             :       }
     108             : 
     109             :       //"extrapolation" is not mandatory
     110             :       const char* extrapolation;
     111           0 :       extrapolation = currFilterNode->Attribute("extrapolation");
     112             : 
     113           0 :       if (sequential)
     114           0 :         newfilter = new coupling::filtering::Gauss<dim>(inputCellVector, outputCellVector, _filteredValues, (unsigned int)d, sigma, extrapolation);
     115             :       else
     116           0 :         newfilter = new coupling::filtering::Gauss<dim, coupling::indexing::IndexTrait::local>(inputCellVector, outputCellVector, _filteredValues,
     117             :                                                                                                (unsigned int)d, sigma, extrapolation);
     118             :     }
     119             : 
     120             :     // POD
     121           0 :     else if (std::strcmp(currFilterNode->Value(), "POD") == 0) {
     122             : #ifdef BUILD_WITH_EIGEN
     123             :       // In earlier implementations, it used to be possible to override tws via
     124             :       // function parameter. This feature was removed. See:
     125             :       // coupling::noisereduction::NoiseReductionConfiguration::interpreteConfiguration<dim>(...,
     126             :       // int tws)
     127             :       int tws;
     128             :       if (currFilterNode->QueryIntAttribute("time-window-size", &tws)) {
     129             :         std::cout << "ERROR: POD filter misses attribute time-window-size in "
     130             :                      "config file."
     131             :                   << std::endl;
     132             :         exit(EXIT_FAILURE);
     133             :       }
     134             :       if (tws <= 2) {
     135             :         std::cout << "ERROR: POD: time-window-size must be greater than two." << std::endl;
     136             :         exit(EXIT_FAILURE);
     137             :       }
     138             :       int kmax;
     139             :       if (currFilterNode->QueryIntAttribute("kmax", &kmax)) {
     140             :         std::cout << "ERROR: POD filter misses attribute kmax in config file." << std::endl;
     141             :         exit(EXIT_FAILURE);
     142             :       }
     143             :       if (kmax <= 0) {
     144             :         std::cout << "ERROR: POD: kmax must be greater than zero.";
     145             :         exit(EXIT_FAILURE);
     146             :       }
     147             : 
     148             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     149             :       newfilter = new coupling::filtering::POD<dim>(inputCellVector, outputCellVector, _comm, _filteredValues, tws, kmax);
     150             : #else
     151             :       newfilter = new coupling::filtering::POD<dim>(inputCellVector, outputCellVector, _filteredValues, tws, kmax);
     152             : #endif
     153             : #else
     154           0 :       std::cout << "ERROR: BUILD_WITH_EIGEN was not defined but filter node was set to POD." << std::endl;
     155           0 :       exit(EXIT_FAILURE);
     156             : #endif
     157             :     }
     158             : 
     159             :     // TODO: refactor the following filters to fit to new type system
     160             :     /*
     161             :             //Strouhal
     162             :             else if(std::strcmp(currFilterNode->Value(), "strouhal") == 0) {
     163             :                     double d;
     164             :                     if(currFilterNode->QueryDoubleAttribute("D", &d)){
     165             :                             std::cout << "ERROR: Strouhal filter misses
     166             :     attribute D in config file." << std::endl; exit(EXIT_FAILURE);
     167             :                     }
     168             :                     double u;
     169             :                     if(currFilterNode->QueryDoubleAttribute("U", &u)){
     170             :                             std::cout << "ERROR: Strouhal filter misses
     171             :     attribute U in config file." << std::endl; exit(EXIT_FAILURE);
     172             :                     }
     173             :                     newfilter = new
     174             :     coupling::filtering::Strouhal<dim>(inputCellVector, outputCellVector,
     175             :     _sequenceDomainCellIndices, _filteredValues, u , d);
     176             :     }
     177             :     */
     178             : 
     179             :     // ###############################################################
     180             : 
     181             :     // Unknown filter identifier
     182             :     else {
     183           0 :       std::cout << "ERROR: Filter-Sequence does not recognize filter called " << currFilterNode->Value() << std::endl;
     184           0 :       exit(EXIT_FAILURE);
     185             :     }
     186             : 
     187             : // sequential filtering
     188             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     189           0 :     if (sequential)
     190           0 :       _filters.push_back(new coupling::filtering::SequentialFilter<dim>(newfilter, _comm));
     191             :     else
     192             : #endif
     193           0 :       _filters.push_back(newfilter);
     194             : 
     195           0 :     if (firstIteration) {
     196           0 :       inputCellVector = _cellVector1;
     197             :       firstIteration = false;
     198             :     }
     199             : 
     200           0 :     inputCellVector.swap(outputCellVector);
     201           0 :     currFilterNode = currFilterNode->NextSiblingElement();
     202             :   }
     203             : 
     204             :   // Check for modfiability. By default true.
     205           0 :   if (const char* modifiable = sequenceNode->Attribute("modifiable")) {
     206           0 :     if (std::strcmp(modifiable, "false") == 0)
     207           0 :       _isModifiable = false;
     208             :   }
     209             : 
     210             : #ifdef DEBUG_FILTER_PIPELINE
     211             :   std::cout << PRINT_PREFIX();
     212             :   printOutputCellVector();
     213             : #endif
     214             : 
     215           0 :   return 0;
     216           0 : }
     217             : 
     218             : // TODO: restructure code: reduce code duplication
     219             : template <unsigned int dim>
     220           0 : void coupling::filtering::FilterSequence<dim>::addFilter(
     221             :     const std::function<std::vector<double>(std::vector<double>, std::vector<std::array<unsigned int, dim>>)>* applyScalar,
     222             :     const std::function<std::vector<std::array<double, dim>>(std::vector<std::array<double, dim>>, std::vector<std::array<unsigned int, dim>>)>* applyVector,
     223             :     int filterIndex // counting starts at 0, -1 is equivalent to EOL
     224             : ) {
     225             :   // save state before tinkering with output cells
     226           0 :   auto outputCellVectorBefore = getOutputCellVector();
     227             : 
     228           0 :   if (_isModifiable) {
     229           0 :     const unsigned int index = (filterIndex == -1 || filterIndex > (int)_filters.size()) ? _filters.size() : filterIndex;
     230             : 
     231             :     // case: index 0
     232           0 :     if (index == 0) {
     233             :       // previous filter at index 0 won't use _inputCellVector any longer
     234           0 :       if (!_filters.empty())
     235           0 :         _filters[0]->setInputCells(_cellVector1);
     236             : 
     237           0 :       _filters.insert(_filters.begin() + index,
     238           0 :                       new coupling::filtering::FilterFromFunction<dim>(_inputCellVector, _cellVector2, _filteredValues, applyScalar, applyVector));
     239             : 
     240             :       // add copy if no copy after index exists, else remove that copy
     241           0 :       if (_filters.size() > 1) { // dont check if the newly added FFF is the
     242             :                                  // only filter in the sequence
     243           0 :         if (std::strcmp(_filters[1]->getType(), "COPY") == 0)
     244           0 :           _filters.erase(_filters.begin() + 1);
     245             :         else
     246           0 :           _filters.insert(_filters.begin() + 1, new coupling::filtering::Copy<dim>(_cellVector2, _cellVector1, _filteredValues));
     247             :       } else
     248           0 :         _filters.insert(_filters.begin() + 1, new coupling::filtering::Copy<dim>(_cellVector2, _cellVector1, _filteredValues));
     249             : #ifdef DEBUG_FILTER_PIPELINE
     250             :       std::cout << PRINT_PREFIX() << "Inserted new filter at index 0" << std::endl;
     251             : #endif
     252             :     }
     253             : 
     254             :     // case: appending to nonempty sequence
     255           0 :     else if (index == _filters.size()) {
     256           0 :       if (_filters.size() % 2 == 0)
     257           0 :         _filters.push_back(new coupling::filtering::FilterFromFunction<dim>(_cellVector1, _cellVector2, _filteredValues, applyScalar, applyVector));
     258             :       else
     259           0 :         _filters.push_back(new coupling::filtering::FilterFromFunction<dim>(_cellVector2, _cellVector1, _filteredValues, applyScalar, applyVector));
     260             : #ifdef DEBUG_FILTER_PIPELINE
     261             :       std::cout << PRINT_PREFIX() << "Appended new filter to sequence." << std::endl;
     262             : #endif
     263             :     }
     264             : 
     265             :     // case: inserting at nonzero index
     266             :     else {
     267           0 :       if (index % 2 == 0) {
     268           0 :         _filters.insert(_filters.begin() + index,
     269           0 :                         new coupling::filtering::FilterFromFunction<dim>(_cellVector1, _cellVector2, _filteredValues, applyScalar, applyVector));
     270             : 
     271             :         // add copy if no copy after index exists, else remove that copy
     272           0 :         if (std::strcmp(_filters[index + 1]->getType(), "COPY") == 0)
     273           0 :           _filters.erase(_filters.begin() + index + 1);
     274             :         else
     275           0 :           _filters.insert(_filters.begin() + index + 1, new coupling::filtering::Copy<dim>(_cellVector2, _cellVector1, _filteredValues));
     276             :       } else {
     277           0 :         _filters.insert(_filters.begin() + index,
     278           0 :                         new coupling::filtering::FilterFromFunction<dim>(_cellVector2, _cellVector1, _filteredValues, applyScalar, applyVector));
     279             : 
     280             :         // add copy if no copy after index exists, else remove that copy
     281           0 :         if (std::strcmp(_filters[index + 1]->getType(), "COPY") == 0)
     282           0 :           _filters.erase(_filters.begin() + index + 1);
     283             :         else
     284           0 :           _filters.insert(_filters.begin() + index + 1, new coupling::filtering::Copy<dim>(_cellVector1, _cellVector2, _filteredValues));
     285             :       }
     286             : #ifdef DEBUG_FILTER_PIPELINE
     287             :       std::cout << PRINT_PREFIX() << "Inserted new filter at index " << index << std::endl;
     288             : #endif
     289             :     }
     290             : #ifdef DEBUG_FILTER_PIPELINE
     291             :     std::cout << PRINT_PREFIX();
     292             :     printOutputCellVector();
     293             : #endif
     294             :   } else
     295             :     std::cout << "WARNING: Trying to add filter at runtime to non-modifiable "
     296             :                  "filter sequence "
     297           0 :               << _name << ". Refused." << std::endl; // exit()?
     298             : 
     299             :   // Check if output vector has changed. Currently, this can only happen if the
     300             :   // output vector was _inputCellVector before.
     301           0 :   if (outputCellVectorBefore != getOutputCellVector()) {
     302           0 :     for (auto child : _childSequences) {
     303           0 :       child->updateInputCellVector(getOutputCellVector());
     304             : #ifdef DEBUG_FILTER_PIPELINE
     305             :       std::cout << PRINT_PREFIX() << "Reported change in output vector to child sequence " << child->getName() << std::endl;
     306             : #endif
     307             :     }
     308             :   }
     309           0 : }
     310             : 
     311             : // Private functions of coupling::filtering::FilterSequence
     312             : 
     313             : // TODO: inline in constructor
     314           0 : template <unsigned int dim> void coupling::filtering::FilterSequence<dim>::initCellVectors() {
     315           0 :   for (auto cell : _inputCellVector) {
     316           0 :     _cellVector1.push_back(new coupling::datastructures::CouplingCell<dim>(*cell));
     317           0 :     _cellVector2.push_back(new coupling::datastructures::CouplingCell<dim>(*cell));
     318             :   }
     319             : #ifdef DEBUG_FILTER_PIPELINE
     320             :   std::cout << PRINT_PREFIX() << "Initialized cell vectors." << std::endl;
     321             : #endif
     322           0 : }

Generated by: LCOV version 1.14