//====================================================================================================================== // // This file is part of waLBerla. waLBerla is free software: you can // redistribute it and/or modify it under the terms of the GNU General Public // License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // waLBerla is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see . // //! \file Cell.h //! \ingroup core //! \author Christian Godenschwager //! \author Florian Schornbaum // //====================================================================================================================== #pragma once #include "core/DataTypes.h" #include "core/debug/Debug.h" #include "core/mpi/BufferSizeTrait.h" #include "core/mpi/RecvBuffer.h" #include "core/mpi/SendBuffer.h" #include #include #include namespace walberla { namespace cell { /*******************************************************************************************************************//** * \brief A representation of a Cell's coordinates (in 3D) **********************************************************************************************************************/ class Cell { public: /*! \name Constructors */ //@{ Cell() = default; inline Cell( const cell_idx_t _x, const cell_idx_t _y, const cell_idx_t _z ) { cell[0] = _x; cell[1] = _y; cell[2] = _z; } //inline Cell( const int _x, const int _y, const int _z ); inline Cell( const uint_t _x, const uint_t _y, const uint_t _z ); //@} /*! \name Arithmetic operators */ //@{ inline Cell operator+( const Cell & rhs ) const; inline Cell operator-( const Cell & rhs ) const; inline Cell & operator+=( const Cell & rhs ); inline Cell & operator-=( const Cell & rhs ); inline Cell operator+() const; inline Cell operator-() const; //@} /*! \name Comparison operators */ //@{ bool operator< ( const Cell & rhs ) const; bool operator==( const Cell & rhs ) const; bool operator!=( const Cell & rhs ) const { return !operator==( rhs ); } //@} /*! \name Access operators */ //@{ cell_idx_t operator[]( std::size_t idx ) const; cell_idx_t & operator[]( std::size_t idx ); cell_idx_t x() const { return cell[0]; } cell_idx_t & x() { return cell[0]; } cell_idx_t y() const { return cell[1]; } cell_idx_t & y() { return cell[1]; } cell_idx_t z() const { return cell[2]; } cell_idx_t & z() { return cell[2]; } //@} bool positiveIndicesOnly() const { return x() >= cell_idx_c(0) && y() >= cell_idx_c(0) && z() >= cell_idx_c(0); } private: cell_idx_t cell[3]; ///< Array of the cells coordinates. cell == {x, y, z}. }; /*! \name Stream operators */ //@{ std::ostream & operator<<( std::ostream & os, const Cell & cell ); std::istream & operator>>( std::istream & is, Cell & cell ); //@} // inline Cell::Cell( const int _x, const int _y, const int _z ) { // // x() = cell_idx_c( _x ); y() = cell_idx_c( _y ); z() = cell_idx_c( _z ); // } inline Cell::Cell( const uint_t _x, const uint_t _y, const uint_t _z ) { cell[0] = cell_idx_c( _x ); cell[1] = cell_idx_c( _y ); cell[2] = cell_idx_c( _z ); } /*******************************************************************************************************************//** * \brief Less-than comparison operator for Cells. * * Compares a cell's coordinates lexicographically (first x, then eventually y and (if necessary) finally z). * * \param [in] rhs the cell compared to *this. * * \return \code std::lexicographical_compare(this->cell, this->cell + 3, rhs.cell, rhs.cell + 3). \endcode **********************************************************************************************************************/ inline bool Cell::operator<( const Cell & rhs ) const { return std::lexicographical_compare( std::reverse_iterator( this->cell + 3 ), std::reverse_iterator( this->cell ), std::reverse_iterator( rhs.cell + 3 ), std::reverse_iterator( rhs.cell ) ); } /******************************************************************************************************************//** * \brief Equal comparison operator for Cells. * * Compares a cell's coordinates for equality (first x, then eventually y and (if necessary) finally z). * * \param [in] rhs The cell compared to *this. * * \return \code (this->x == rhs.x) && (this->y == rhs.y) && (this->z == rhs.z) \endcode **********************************************************************************************************************/ inline bool Cell::operator==( const Cell & rhs ) const { return ( this->x() == rhs.x() ) && ( this->y() == rhs.y() ) && ( this->z() == rhs.z() ); } /*******************************************************************************************************************//** * \brief Operator providing read-only element access of a const Cell. * * \param [in] idx Zero-based index of the cell's coordinate component. * * \return The idx-th coordinate component. This is equal to this->cell[i]. **********************************************************************************************************************/ inline cell_idx_t Cell::operator[]( std::size_t idx ) const { WALBERLA_ASSERT_LESS( idx, 3, "Index 'idx' = " << idx << " out of bounds! Cell: " << *this ); return cell[idx]; } /*******************************************************************************************************************//** * \brief Operator for component-wise addition of two cells. * * \param [in] rhs The cell added to this. * * \return a Cell which components are the sum of this and rhs components **********************************************************************************************************************/ Cell Cell::operator+( const Cell & rhs ) const { Cell result; result.cell[0] = cell[0] + rhs.cell[0]; result.cell[1] = cell[1] + rhs.cell[1]; result.cell[2] = cell[2] + rhs.cell[2]; return result; } /*******************************************************************************************************************//** * \brief Operator for component-wise subtraction of two cells. * * \param [in] rhs The cell subtracted from this. * * \return a Cell which components are the difference of this and rhs components **********************************************************************************************************************/ Cell Cell::operator-( const Cell & rhs ) const { Cell result; result.cell[0] = cell[0] - rhs.cell[0]; result.cell[1] = cell[1] - rhs.cell[1]; result.cell[2] = cell[2] - rhs.cell[2]; return result; } /*******************************************************************************************************************//** * \brief Additive compound assignment operator. * * \param [in] rhs The cell added to this. * * \return Reference to this. **********************************************************************************************************************/ Cell & Cell::operator+=( const Cell & rhs ) { cell[0] += rhs.cell[0]; cell[1] += rhs.cell[1]; cell[2] += rhs.cell[2]; return *this; } /*******************************************************************************************************************//** * \brief Subtractive compound assignment operator. * * \param [in] rhs The cell subtracted from this. * * \return Reference to this. **********************************************************************************************************************/ Cell & Cell::operator-=( const Cell & rhs ) { cell[0] -= rhs.cell[0]; cell[1] -= rhs.cell[1]; cell[2] -= rhs.cell[2]; return *this; } /*******************************************************************************************************************//** * \brief Unary plus operator. * * \return *this unmodified. **********************************************************************************************************************/ inline Cell Cell::operator+() const { return *this; } /*******************************************************************************************************************//** * \brief Unary negation operator. * * \return Cell with negated components. **********************************************************************************************************************/ inline Cell Cell::operator-() const { return Cell( -x(), -y(), -z() ); } /******************************************************************************************************************//** * \brief Operator providing element access of a Cell. * * \param [in] idx Zero-based index of the cell's coordinate component. * * \return The idx-th coordinate component. This is equal to this->cell[i]. **********************************************************************************************************************/ inline cell_idx_t & Cell::operator[]( std::size_t idx ) { WALBERLA_ASSERT_LESS( idx, 3, "Index 'idx' = " << idx << " out of bounds! Cell: " << *this ); return cell[idx]; } /*******************************************************************************************************************//** * \brief Stream output operator for a Cell object. * * Serializes a Cell like (x,y,z). Example: (7,36,1211). * * \param [in,out] os The output stream. * \param [in] cell The cell to be serialized. * * \return A reference to the modified output stream. **********************************************************************************************************************/ inline std::ostream & operator<<( std::ostream & os, const Cell & cell ) { os << "(" << cell.x() << "," << cell.y() << "," << cell.z() << ")"; return os; } /*******************************************************************************************************************//** * \brief Stream input operator for a Cell object. * * Deserializes a Cell like (x,y,z). Example: (7,36,1211). Whitespaces between commas or brackets * are ignored. * * \param [in,out] is The input stream. * \param [out] cell The result cell. * * \return A reference to the modified input stream. **********************************************************************************************************************/ inline std::istream & operator>>( std::istream & is, Cell & cell ) { if( !is ) return is; char bracket1, bracket2, comma1, comma2; cell_idx_t x(0), y(0), z(0); const std::istream::pos_type pos( is.tellg() ); const std::istream::fmtflags oldFlags( is.flags() ); // Setting the 'skip whitespaces' flag is >> std::skipws; // Extracting the vector if( !(is >> bracket1 >> x >> comma1 >> y >> comma2 >> z >> bracket2) || bracket1 != '(' || comma1 != ',' || comma2 != ',' || bracket2 != ')' ) { is.clear(); is.seekg( pos ); is.setstate( std::istream::failbit ); is.flags( oldFlags ); return is; } // Transferring the input to the vector values cell.x() = x; cell.y() = y; cell.z() = z; // Resetting the flags is.flags( oldFlags ); return is; } /*******************************************************************************************************************//** * \brief Provides a hash value for a Cell based on its coordinates. * * \param [in] cell The cell to be hashed. * * \return a hopefully unique hash. **********************************************************************************************************************/ inline std::size_t hash_value( const Cell & cell ) { std::size_t seed = 0; std::hash hasher; seed ^= hasher(cell.x()) + 0x9e3779b9 + (seed<<6) + (seed>>2); seed ^= hasher(cell.y()) + 0x9e3779b9 + (seed<<6) + (seed>>2); seed ^= hasher(cell.z()) + 0x9e3779b9 + (seed<<6) + (seed>>2); return seed; } //====================================================================================================================== // // Send/Recv Buffer Serialization Specialization // //====================================================================================================================== template< typename T, // Element type of SendBuffer typename G > // Growth policy of SendBuffer mpi::GenericSendBuffer& operator<<( mpi::GenericSendBuffer & buf, const Cell & cell ) { return buf << cell.x() << cell.y() << cell.z(); } template< typename T > // Element type of RecvBuffer mpi::GenericRecvBuffer& operator>>( mpi::GenericRecvBuffer & buf, Cell & cell ) { return buf >> cell.x() >> cell.y() >> cell.z(); } } // namespace cell using cell::Cell; namespace mpi { template<> struct BufferSizeTrait< Cell> { static const bool constantSize = true; static const uint_t size = 3 * sizeof(cell_idx_t) + BUFFER_DEBUG_OVERHEAD; }; } } // namespace walberla namespace std { template<> struct hash< walberla::Cell > { std::size_t operator()( walberla::Cell const & cell ) const noexcept { return walberla::cell::hash_value( cell ); } }; } // namespace std