An error occurred while loading the file. Please try again.
-
Christian Godenschwager authored
If you have access to the old closed source waLBerla repository, you may restore the complete history with the following command git fetch git@i10git.cs.fau.de:software/walberla.git 'refs/replace/*:refs/replace/*'
bf76deb1
Forked from
waLBerla / waLBerla
1869 commits behind the upstream repository.
BlockCellDataWriter.h 16.27 KiB
//======================================================================================================================
//
// 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 <http://www.gnu.org/licenses/>.
//
//! \file BlockCellDataWriter.h
//! \ingroup vtk
//! \author Florian Schornbaum <florian.schornbaum@fau.de>
//
//======================================================================================================================
#pragma once
#include "Base64Writer.h"
#include "UtilityFunctions.h"
#include "core/DataTypes.h"
#include "core/debug/Debug.h"
#include "domain_decomposition/StructuredBlockStorage.h"
#include <ostream>
#include <string>
namespace walberla {
namespace vtk {
namespace internal {
//**********************************************************************************************************************
/*!
* \brief Interface that is used by VTKOutput in order to write data to VTK files
*
* If one wants to write block data to a VTK file, one must implement a class that derives from
* vtk::internal::BlockCellDataWriter. An instance of this class then can be registered at a VTKOutput object. Every
* time the output function of this VTKOutput object is triggered, all registered BlockCellDataWriter objects are
* called.
*
* Implementations of vtk::internal::BlockCellDataWriter are not supposed to inherit directly from
* vtk::internal::BlockCellDataWriter but from vtk::BlockCellDataWriter which provides a much nicer interface for the
* user to implement!
*
* Every class derived from BlockCellDataWriter must implement two push functions that write one data element to either
* an output stream or a Base64Writer. Typically, a private "evaluate" function is implemented and called in both push
* functions:
* \code
* void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f )
* {
* vtk::toStream( os, evaluate(x,y,z,f) ); // to prevent the data output stream from writing ascii characters
* // for [unsigned] char data instead of numbers
* }
*
* void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f )
* {
* b64 << evaluate(x,y,z,f);
* }
*
* [DataType] evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) { ... }
* \endcode
* Both push functions always receive block local cell coordinates corresponding to the two protected members "block_"
* and "blockStorage_".
* The data elements which are pushed to the stream/Base64Writer must always be of the same type! Every data type is
* assigned a specific string in VTK. This string must be returned by the pure virtual member function "typeString()".
* This function should always be implemented by calling the utility function "vtk::typeToString()":
* \code
* const std::string& typeString() const { return vtk::typeToString< [DataType] >(); }
* \endcode
*
* Additionally, every class derived from BlockCellDataWriter can implement two further push functions that are used
* for resampling the data. The parameters passed to these two functions are as follows:
* - os/b64: the output stream/base64 writer
* - x/y/z: block local cell coordinates of the cell that contains the point (globalX,globalY,globalZ)
* - f: the "f value"/"dimension"/number of components
* - local[X/Y/Z]Cell: coordinates of the point (globalX,globalY,globalZ) in block local cell coordinates
* In contrast to x/y/z (which are discrete values!), these coordinates are continuous/exact.
* - global[X/Y/Z]: the center of the "resampled" cell in global coordinates (within the global 3D simulation space)
* - samplingD[x/y/z]: the size/extent of the "resampled" cell in x-/y-/z-direction
* If you do not provide your own implementation of these two functions, than the default implementation provided by
* class BlockCellDataWriter is used which performs a simple nearest neighbor interpolation:
* \code
* void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
* const real_t, const real_t, const real_t, const real_t, const real_t, const real_t,
* const real_t, const real_t, const real_t ) { push( os, x, y, z, f ); }
*
* void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
* const real_t, const real_t, const real_t, const real_t, const real_t, const real_t,
* const real_t, const real_t, const real_t ) { push( b64, x, y, z, f ); }
* \endcode
*
* Every time "configure( const IBlock& block, const StructuredBlockStorage& sbs )" is called, the block and its
* corresponding structured block storage assigned to the BlockCellDataWriter may change. This triggers the call of a
* protected member function "configure()" which must be implemented and is intended for reacting to these changes.
*
*/
//**********************************************************************************************************************
class BlockCellDataWriter
{
public:
BlockCellDataWriter( const std::string& id ) : block_( NULL ), blockStorage_( NULL ), identifier_( id ) {}
virtual ~BlockCellDataWriter() {}
void configure( const IBlock& block, const StructuredBlockStorage& sbs ) { block_ = █ blockStorage_ = &sbs; configure(); }
/// For the documentation of this function, please refer to the documentation/general description of this class.
virtual void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) = 0;
/// For the documentation of this function, please refer to the documentation/general description of this class.
virtual void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) = 0;
/// For the documentation of this function, please refer to the documentation/general description of this class.
virtual inline void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t localXCell, const real_t localYCell, const real_t localZCell,
const real_t globalX, const real_t globalY, const real_t globalZ,
const real_t samplingDx, const real_t samplingDy, const real_t samplingDz );
/// For the documentation of this function, please refer to the documentation/general description of this class.
virtual inline void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t localXCell, const real_t localYCell, const real_t localZCell,
const real_t globalX, const real_t globalY, const real_t globalZ,
const real_t samplingDx, const real_t samplingDy, const real_t samplingDz );
uint_t xSize() const { WALBERLA_ASSERT_NOT_NULLPTR( block_ ); WALBERLA_ASSERT_NOT_NULLPTR( blockStorage_ ); return blockStorage_->getNumberOfXCells( *block_ ); }
uint_t ySize() const { WALBERLA_ASSERT_NOT_NULLPTR( block_ ); WALBERLA_ASSERT_NOT_NULLPTR( blockStorage_ ); return blockStorage_->getNumberOfYCells( *block_ ); }
uint_t zSize() const { WALBERLA_ASSERT_NOT_NULLPTR( block_ ); WALBERLA_ASSERT_NOT_NULLPTR( blockStorage_ ); return blockStorage_->getNumberOfZCells( *block_ ); }
virtual uint_t fSize() const = 0; //!< must return the size of the fourth dimension
/*!< (data fields storing scalar values return "1", data fields storing
* vector data return the size of the vector) */
//*******************************************************************************************************************
/*!
* Every data type is assigned a specific string in VTK. This string must be returned by this function, which should
* always be implemented by calling the utility function "vtk::typeToString()":
* \code
* const std::string& typeString() const { return vtk::typeToString< [DataType] >(); }
* \endcode
*/
//*******************************************************************************************************************
virtual const std::string & typeString() const = 0;
const std::string & identifier() const { return identifier_; };
protected:
//*******************************************************************************************************************
/*!
* Every time "configure( const IBlock& block, const StructuredBlockStorage& sbs )" is called, the block and its
* corresponding structured block storage assigned to the BlockCellDataWriter may change. This triggers the call of
* this function which must be implemented and is intended for reacting to these changes.
*/
//*******************************************************************************************************************
virtual void configure() = 0;
void setIdentifier( const std::string & id ) { this->identifier_ = id; }
const IBlock* block_;
const StructuredBlockStorage* blockStorage_;
std::string identifier_;
private:
BlockCellDataWriter() {}
}; // class BlockCellDataWriter
inline void BlockCellDataWriter::push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t /*localXCell*/, const real_t /*localYCell*/, const real_t /*localZCell*/,
const real_t /*globalX*/, const real_t /*globalY*/, const real_t /*globalZ*/,
const real_t /*samplingDx*/, const real_t /*samplingDy*/, const real_t /*samplingDz*/ )
{
push( os, x, y, z, f );
}
inline void BlockCellDataWriter::push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t /*localXCell*/, const real_t /*localYCell*/, const real_t /*localZCell*/,
const real_t /*globalX*/, const real_t /*globalY*/, const real_t /*globalZ*/,
const real_t /*samplingDx*/, const real_t /*samplingDy*/, const real_t /*samplingDz*/ )
{
push( b64, x, y, z, f );
}
} // namespace internal
typedef internal::BlockCellDataWriter BlockCellDataWriterInterface;
//**********************************************************************************************************************
/*!
* \brief Interface that is used by VTKOutput in order to write data to VTK files
*
* For a detailed documentation see the documentation of class vtk::internal::BlockCellDataWriter.
*
* Classes deriving from BlockCellDataWriter must implement a protected member function "evaluate(x,y,z,f)" and
* "configure()" [pure virtual function inherited from vtk::internal::BlockCellDataWriter]. They can also implement a
* second evaluate function used during resampling (if this function is not implemented nearest neighbor interpolation
* will be used for resampling the data).
*/
//**********************************************************************************************************************
template< typename T, uint_t F_SIZE_ARG = 1u >
class BlockCellDataWriter : public BlockCellDataWriterInterface
{
public:
typedef T value_type;
static const uint_t F_SIZE = F_SIZE_ARG;
BlockCellDataWriter( const std::string & id ) : BlockCellDataWriterInterface( id ) {}
virtual ~BlockCellDataWriter() {}
void push( std::ostream & os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f )
{
vtk::toStream( os, evaluate( x, y, z, f ) );
}
void push( vtk::Base64Writer & b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f )
{
b64 << evaluate( x, y, z, f );
}
void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t localXCell, const real_t localYCell, const real_t localZCell,
const real_t globalX, const real_t globalY, const real_t globalZ,
const real_t samplingDx, const real_t samplingDy, const real_t samplingDz )
{
vtk::toStream( os, evaluate( x, y, z, f, localXCell, localYCell, localZCell,
globalX, globalY, globalZ, samplingDx, samplingDy, samplingDz ) );
}
void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t localXCell, const real_t localYCell, const real_t localZCell,
const real_t globalX, const real_t globalY, const real_t globalZ,
const real_t samplingDx, const real_t samplingDy, const real_t samplingDz )
{
b64 << evaluate( x, y, z, f, localXCell, localYCell, localZCell, globalX, globalY, globalZ, samplingDx, samplingDy, samplingDz );
}
uint_t fSize() const { return F_SIZE; }
const std::string & typeString() const { return vtk::typeToString< T >(); }
protected:
virtual T evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) = 0;
virtual T evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t localXCell, const real_t localYCell, const real_t localZCell,
const real_t globalX, const real_t globalY, const real_t globalZ,
const real_t samplingDx, const real_t samplingDy, const real_t samplingDz );
// virtual void configure() = 0; // -> don't forget to implement this member function!
}; // class BlockCellDataWriter
template< typename T, uint_t F_SIZE_ARG >
inline T BlockCellDataWriter< T, F_SIZE_ARG >::evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f,
const real_t /*localXCell*/, const real_t /*localYCell*/, const real_t /*localZCell*/,
const real_t /*globalX*/, const real_t /*globalY*/, const real_t /*globalZ*/,
const real_t /*samplingDx*/, const real_t /*samplingDy*/, const real_t /*samplingDz*/ )
{
return evaluate(x,y,z,f);
}
template< typename T >
class BlockCellDataWriterScalingAdapter : public T
{
public:
typedef typename T::value_type value_type;
static const uint_t F_SIZE = T::F_SIZE;
BlockCellDataWriterScalingAdapter( const std::string& id, const T & base, value_type factor )
: T( base ), factor_( factor ) { this->setIdentifier( id ); }
protected:
virtual value_type evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f )
{
return factor_ * T::evaluate( x, y, z, f );
}
private:
value_type factor_;
};
template< typename T >
shared_ptr< BlockCellDataWriterScalingAdapter<T> > makeBlockCellDataWriterScalingAdapter(
const std::string& id, const shared_ptr<T> & base, typename T::value_type factor )
{
return walberla::make_shared< BlockCellDataWriterScalingAdapter<T> >( id, *base, factor );
}
} // namespace vtk
} // namespace walberla