LCOV - code coverage report
Current view: top level - coupling/filtering/sequencing - FilterSequence.cpph (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 109 0
Test Date: 2026-08-21 15:14:06 Functions: 0.0 % 3 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 2.0-1