Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions coupling/datastructures/BoxCellContainer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
// This file is part of the Mamico project. For conditions of distribution
// and use, please see the copyright notice in Mamico's main folder
#pragma once

#include "coupling/CouplingMDDefinitions.h"
#include "coupling/datastructures/CouplingCell.h"
#include "coupling/indexing/IndexingService.h"
#include "coupling/datastructures/CellContainer.h"

namespace coupling {
namespace datastructures {
class BoxCellContainer;
} // namespace datastructures
} // namespace coupling

/**
* @brief provides access to the coupling cells. Base class for the class coupling::datastructures::LinkedCellContainer
*
* The BoxCellContainer is intended to be used for an arbitrary rectangular indexing domain defined by a lower and upper bound or lower bound and size.
* Once created, it is assumed to hold all cells in that domain. BoxCellContainers do not capture relevant cells automatically.
* It is the responsibility of the calling function to allocate the cells and populate the container completely before
* using it. Due to this complete and contiguous nature of the datastructure, direct indexing is allowed, and the cell container is expected to start at
* the relative location {0, 0, 0}. BoxCellContainers contain pointers to coupling cells, the cells are not owned by the container, hence
* the calling function must delete the cells later.
*/
class coupling::datastructures::BoxCellContainer {

public:
template<class CellIndexT> BoxCellContainer(coupling::datastructures::CellContainer<CellIndexT, 3> cellContainer)
: BoxCellContainer(CellIndexT::begin(), CellIndexT::numberCellsInDomain) {
for(auto cell : cellContainer)
this << cell;
}

BoxCellContainer(I01 lowerBound, I01 upperBound) : BoxCellContainer({}, lowerBound, upperBound) {}

BoxCellContainer(I01 lowerBound, tarch::la::Vector<3, int> shape) : BoxCellContainer({}, lowerBound, shape) {}

BoxCellContainer(I01 lowerBound, tarch::la::Vector<3, unsigned int> shape) : BoxCellContainer({}, lowerBound, shape) {}

BoxCellContainer(std::vector<coupling::datastructures::CouplingCell<3>*> couplingCells, I01 lowerBound, I01 upperBound)
: BoxCellContainer(couplingCells, lowerBound, (upperBound.get() + tarch::la::Vector<3,int>(1)) - lowerBound.get()) {
}

BoxCellContainer(std::vector<coupling::datastructures::CouplingCell<3>*> couplingCells, I01 lowerBound, tarch::la::Vector<3, unsigned int> shape)
: BoxCellContainer(couplingCells, lowerBound, tarch::la::Vector<3,int>{(int)shape[0], (int)shape[1], (int)shape[2]}){}

BoxCellContainer(std::vector<coupling::datastructures::CouplingCell<3>*> couplingCells, I01 lowerBound, tarch::la::Vector<3, int> shape) : _lowerBound(lowerBound), _shape(shape) {

#if (COUPLING_MD_ERROR == COUPLING_MD_YES)
for (int i = 0; i < 3; i++)
if (shape[i] < 0) {
std::cout << "BoxCellContainer shape must not be negative, but dimension " << i << " was " << shape[i] << std::endl;
std::exit(EXIT_FAILURE);
}
#endif
_couplingCells.reserve(linearNumberCellsInDomain());
for (auto cell : couplingCells) {
*this << cell;
}
}

/** Index based access, returns a pointer to the coupling cell
* @param index index An index of type tarch::la::Vector
* @return the pointer to the requested cell
*/
coupling::datastructures::CouplingCell<3>* operator[](tarch::la::Vector<3, int> index) const {
#if (COUPLING_MD_ERROR == COUPLING_MD_YES)
for (int i = 0; i < 3; i++)
if (index[i] < 0 || index[i] >= numberCellsInDomain()[i]) {
std::cout << "BoxCellContainer accessed out of bounds in dimension " << i;
std::cout << ": " << index[i] << " not in 0-" << numberCellsInDomain()[i] << std::endl;
std::exit(EXIT_FAILURE);
}
if (_couplingCells.size() < linearNumberCellsInDomain()) {
std::cout << "BoxCellContainer accessed but not full " << std::endl;
std::exit(EXIT_FAILURE);
}
#endif
return _couplingCells[indexing::convertToScalar(_lowerBound + index)];
}

/** Adds a new coupling cell to the datastructure at the next index (will only work if the data structure is not yet full)
* @param cell a pointer to the cell to be inserted
*/
void operator<<(coupling::datastructures::CouplingCell<3>* couplingCell) {
#if (COUPLING_MD_ERROR == COUPLING_MD_YES)
if (_couplingCells.size() >= linearNumberCellsInDomain()) {
std::cout << "BoxCellContainer can only hold " << linearNumberCellsInDomain() << " coupling cells!"
<< std::endl;
std::exit(EXIT_FAILURE);
}
#endif
_couplingCells.push_back(couplingCell);
}

/**
* Returns size of the underlying container.
*
* This size is notably not the number of cells in the box domain. However, in practice the two numbers should be identical, as accessing contents of an
* incomplete cotnainer is not allowed.
* @return the number of cells stored currently
*/
unsigned int size() const { return _couplingCells.size(); }

/**
* Returns shape of the underlying box domain.
*
* This size is notably not the number of cells currently held by the datastructure. However, in practice the two numbers should be identical, as accessing contents of an
* incomplete cotnainer is not allowed.
* @return the number of cells in the box domain along each dimension (x, y, z)
*/
tarch::la::Vector<3, int> numberCellsInDomain() const {
return _shape;
}

/**
* Returns size of the underlying box domain.
*
* This size is notably not the number of cells currently held by the datastructure. However, in practice the two numbers should be identical, as accessing contents of an
* incomplete cotnainer is not allowed.
* @return the number of cells in the box domain
*/
unsigned int linearNumberCellsInDomain() const {
int count = 1;
for (int i = 0; i < 3; i++)
count *= _shape[i];
return count;
}

/**
* @brief Provides index iterator functionality
*/
class IndexIterator
{
public:
IndexIterator(I01 lowerBoundary, tarch::la::Vector<3,int>shape, tarch::la::Vector<3,int>offset):_lowerBoundary(lowerBoundary),_shape(shape),_index(offset){}
I01 operator*() const { return _lowerBoundary + _index; }
IndexIterator& operator++() {
// See CellIndex::operator++() in CellIndex.h
++_index[0];
if (_index[0] == (int)_shape[0]) {
_index[0] = 0;
++_index[1];
if (_index[1] == (int)_shape[1]) {
_index[1] = 0;
++_index[2];
}
}
return *this;
}
IndexIterator operator++(int) { IndexIterator tmp = *this; ++(*this); return tmp; }
friend bool operator== (const IndexIterator& a, const IndexIterator& b) {
return a._lowerBoundary == b._lowerBoundary && a._shape == b._shape && a._index == b._index;
}
friend bool operator!= (const IndexIterator& a, const IndexIterator& b) { return !(a == b); };
private:
I01 _lowerBoundary;
tarch::la::Vector<3,int> _shape;
tarch::la::Vector<3,int> _index;
};

/**
* @brief Provides iterator functionality (increment, access as <*cell, index> pair, equality)
*/
class CellIndexIterator {
public:
using CouplingCellIterator = typename std::vector<coupling::datastructures::CouplingCell<3>*>::const_iterator;
CellIndexIterator(CouplingCellIterator itCouplingCells, IndexIterator itIdx) : _itCouplingCells(itCouplingCells), _itIdx(itIdx) {}
/**
* Iterator access, returning the data at the current iterator location
*
* @return a std::pair with the cell pointer and the index of the data that the iterator points to
*/
const std::pair<coupling::datastructures::CouplingCell<3>*, I01> operator*() const { return std::make_pair(*_itCouplingCells, *_itIdx); }
CellIndexIterator& operator++() {
++_itCouplingCells;
++_itIdx;
return *this;
}
CellIndexIterator operator++(int) {
CellIndexIterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const CellIndexIterator& a, const CellIndexIterator& b) {
return a._itCouplingCells == b._itCouplingCells && a._itIdx == b._itIdx;
}
friend bool operator!=(const CellIndexIterator& a, const CellIndexIterator& b) { return !(a == b); }
private:
/**Iterator to underlying cell* vector */
CouplingCellIterator _itCouplingCells;
/**Box and iterator offset of the corresponding container */
IndexIterator _itIdx;
};
/** Provides pointer to beginning of iterator of this container */
CellIndexIterator begin() const {
IndexIterator itIdxBegin = IndexIterator(_lowerBound, _shape, 0);
return CellIndexIterator(_couplingCells.begin(), itIdxBegin);
}
/** Provides pointer to end of iterator of this container */
CellIndexIterator end() const {
// Box with extent _shape means that the last cell is one less in each dimension
tarch::la::Vector<3,int> lastOffset = _shape - tarch::la::Vector<3,int>(1);
// End of iterator is exclusive -> use next index as offset
IndexIterator itIdxEnd = IndexIterator(_lowerBound, _shape, (++I01(lastOffset)).get());
return CellIndexIterator(_couplingCells.end(), itIdxEnd);
}

protected:
/**
* Holds pointers to all coupling cells.
*/
std::vector<coupling::datastructures::CouplingCell<3>*> _couplingCells;
/**
* Defines the lower corner of the box
*/
I01 _lowerBound;
/**
* Defines the extent of the box along all dimensions
*/
tarch::la::Vector<3, int> _shape;
};
11 changes: 5 additions & 6 deletions coupling/filtering/FilterPipeline.cpph
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
// TODO: replace exit()s with throws

// constructors of coupling::filtering::FilterPipeline
template <class CellIndex_T, unsigned int dim>
coupling::filtering::FilterPipeline<CellIndex_T, dim>::FilterPipeline(coupling::datastructures::CellContainer<CellIndex_T, dim> inputCells,
coupling::filtering::FilterPipeline::FilterPipeline(coupling::datastructures::BoxCellContainer inputCells,
coupling::filtering::Scope scope, const tarch::utils::MultiMDService<dim>& multiMDService,
const char* cfgpath)
:
Expand Down Expand Up @@ -100,7 +99,7 @@ coupling::filtering::FilterPipeline<CellIndex_T, dim>::FilterPipeline(coupling::
}

// member functions of coupling::filtering::FilterPipeline
template <class CellIndex_T, unsigned int dim> double coupling::filtering::FilterPipeline<CellIndex_T, dim>::operator()() {
template <class CellIndex_T, unsigned int dim> double coupling::filtering::FilterPipeline::operator()() {
timeval start;
timeval end;
double runtime = 0;
Expand Down Expand Up @@ -144,7 +143,7 @@ template <class CellIndex_T, unsigned int dim> double coupling::filtering::Filte
}

template <class CellIndex_T, unsigned int dim>
coupling::filtering::FilterSequence<dim>* coupling::filtering::FilterPipeline<CellIndex_T, dim>::getSequence(const char* sequenceIdentifier) const {
coupling::filtering::FilterSequence<dim>* coupling::filtering::FilterPipeline::getSequence(const char* sequenceIdentifier) const {
for (auto sequence : _sequences) {
if (std::strcmp(sequence->getName(), sequenceIdentifier) == 0) {
return sequence;
Expand All @@ -155,7 +154,7 @@ coupling::filtering::FilterSequence<dim>* coupling::filtering::FilterPipeline<Ce

// Private functions of coupling::filtering::FilterPipeline:
template <class CellIndex_T, unsigned int dim>
bool coupling::filtering::FilterPipeline<CellIndex_T, dim>::configIsValid(ParseConfiguration::XMLConfiguration& xmlConfig) {
bool coupling::filtering::FilterPipeline::configIsValid(ParseConfiguration::XMLConfiguration& xmlConfig) {
// Check main node
tinyxml2::XMLElement* node = xmlConfig.root->FirstChildElement("filter-pipeline");
if (!node) {
Expand Down Expand Up @@ -205,7 +204,7 @@ bool coupling::filtering::FilterPipeline<CellIndex_T, dim>::configIsValid(ParseC
return true;
}

template <class CellIndex_T, unsigned int dim> void coupling::filtering::FilterPipeline<CellIndex_T, dim>::loadSequencesFromXML(tinyxml2::XMLElement* node) {
template <class CellIndex_T, unsigned int dim> void coupling::filtering::FilterPipeline::loadSequencesFromXML(tinyxml2::XMLElement* node) {

if (_md2MacroCells.empty()) {
switch (_scope) { /*TODO: print rank as well */
Expand Down
31 changes: 8 additions & 23 deletions coupling/filtering/FilterPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,9 @@ using tarch::configuration::ParseConfiguration;

namespace coupling {
namespace filtering {
template <class CellIndex_T, unsigned int dim> class FilterPipeline;

/*
* Used as member of FilterPipeline. Displays where that FP is used.
* per instance: apply filtering for each MD instance
* individually, before merging instances post multi instance: apply filtering
* after MD instances have been merged
*/
enum class Scope { perInstance, postMultiInstance };
class FilterPipeline;

} // namespace filtering
} // namespace coupling

Expand All @@ -41,15 +35,14 @@ enum class Scope { perInstance, postMultiInstance };
*
* @author Felix Maurer
*/
template <class CellIndex_T, unsigned int dim> class coupling::filtering::FilterPipeline {
class coupling::filtering::FilterPipeline {
public:
FilterPipeline(const coupling::datastructures::CellContainer<CellIndex_T, dim> inputCells, const coupling::filtering::Scope scope,
FilterPipeline(const coupling::datastructures::BoxCellContainer inputCells,
const tarch::utils::MultiMDService<dim>& multiMDService, const char* cfgpath);

~FilterPipeline() {
for (auto sequence : _sequences)
delete sequence;
// TODO: do i have to delete the _...cells as well?

#ifdef DEBUG_FILTER_PIPELINE
std::cout << "FP: FilterPipeline deconstructed." << std::endl;
Expand All @@ -58,7 +51,7 @@ template <class CellIndex_T, unsigned int dim> class coupling::filtering::Filter

/*
* Applies each FilterSequence in order of their appearance in the config
* file. Ouput of the specified output-FilterSequence will be written to
* file. Output of the specified output-FilterSequence will be written to
* _md2MacroCells.
*
* @returns The runtime of the filter pipeline in usec.
Expand Down Expand Up @@ -99,20 +92,12 @@ template <class CellIndex_T, unsigned int dim> class coupling::filtering::Filter
/*
* Input cells within the local, md2macro, ghost layer excluding domain
*/
std::vector<coupling::datastructures::CouplingCell<dim>*> _md2MacroCells;
/*
* Input cells that do not match the criteria to be in _md2MacroCells.
*/
std::vector<coupling::datastructures::CouplingCell<dim>*> _outerCells;
coupling::datastructures::BoxCellContainer _md2MacroCells;

coupling::datastructures::BoxCellContainer _allCells;

ParseConfiguration::XMLConfiguration _config;

/*
* Scope in which this FilterPipeline is applied. Cf. coupling::Scope
* definition.
*/
const coupling::filtering::Scope _scope;

std::vector<coupling::filtering::FilterSequence<dim>*> _sequences;

#if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
Expand Down
1 change: 1 addition & 0 deletions coupling/indexing/CellIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ template <unsigned int dim, coupling::indexing::IndexTrait... traits> class coup
*/
CellIndex& operator++() {
if constexpr (std::is_same_v<value_T, tarch::la::Vector<dim, int>>) {
// See IndexIterator::operator++() in BoxCellContainer.h
++_index[0];
if (_index[0] == (int)numberCellsInDomain[0]) {
_index[0] = 0;
Expand Down
Loading