Commit 23072e16 authored by Marcus Mohr's avatar Marcus Mohr
Browse files

Extending capabilities of VTKOutput

This commit changes VTKOutput so that it export also functions of the
following kind:
- P1Function< int32_t >
- P1Function< int64_t >
and not only P1Function< double >.

For this we replace the std::vector< P1Function< real_t > > in the class
by an object of type FunctionMultiStore. This new class allows to store
multiple functions from the same family, which can but need not differ in
their value types.
parent 07b9171d
Pipeline #33718 passed with stages
in 120 minutes and 41 seconds
......@@ -76,11 +76,6 @@ void VTKOutput::add( const P2VectorFunction< real_t >& function )
p2VecFunctions_.push_back( function );
}
void VTKOutput::add( const P1Function< real_t >& function )
{
p1Functions_.push_back( function );
}
void VTKOutput::add( const EdgeDoFFunction< real_t >& function )
{
edgeDoFFunctions_.push_back( function );
......@@ -288,10 +283,21 @@ void VTKOutput::write( const uint_t& level, const uint_t& timestep ) const
void VTKOutput::syncAllFunctions( const uint_t& level ) const
{
for ( const auto& function : p1Functions_ )
// P1Functions [double, int32_t, int64_t] -------------------------------------------------------------------
for ( const auto& function : p1Functions_.getFunctions<double>() )
{
hyteg::communication::syncFunctionBetweenPrimitives< hyteg::P1Function< double > >( function, level );
}
for ( const auto& function : p1Functions_.getFunctions<int32_t>() )
{
hyteg::communication::syncFunctionBetweenPrimitives< hyteg::P1Function< int32_t > >( function, level );
}
for ( const auto& function : p1Functions_.getFunctions<int64_t>() )
{
hyteg::communication::syncFunctionBetweenPrimitives< hyteg::P1Function< real_t > >( function, level );
hyteg::communication::syncFunctionBetweenPrimitives< hyteg::P1Function< int64_t > >( function, level );
}
// P1Functions ----------------------------------------------------------------------------------------------
for ( const auto& function : p1VecFunctions_ )
{
......
......@@ -31,6 +31,7 @@
#include "hyteg/dgfunctionspace/DGFunction.hpp"
#include "hyteg/edgedofspace/EdgeDoFFunction.hpp"
#include "hyteg/functions/BlockFunction.hpp"
#include "hyteg/functions/FunctionMultiStore.hpp"
#include "hyteg/p1functionspace/P1Function.hpp"
#include "hyteg/p2functionspace/P2Function.hpp"
......@@ -70,7 +71,12 @@ class VTKOutput
void setVTKDataFormat( vtk::DataFormat vtkDataFormat ) { vtkDataFormat_ = vtkDataFormat; }
void add( const P1Function< real_t >& function );
template < typename value_t >
inline void add( const P1Function< value_t >& function )
{
p1Functions_.push_back( function );
}
void add( const P2Function< real_t >& function );
void add( const EdgeDoFFunction< real_t >& function );
......@@ -184,7 +190,8 @@ class VTKOutput
bool write2D_;
std::vector< P1Function< real_t > > p1Functions_;
// std::vector< P1Function< real_t > > p1Functions_;
FunctionMultiStore< P1Function > p1Functions_;
std::vector< P2Function< real_t > > p2Functions_;
std::vector< P1VectorFunction< real_t > > p1VecFunctions_;
......
......@@ -74,7 +74,16 @@ void VTKP1Writer::write( const VTKOutput& mgr, std::ostream& output, const uint_
output << "<PointData>\n";
for ( const auto& function : mgr.p1Functions_ )
// write all scalar P1Functions of supported value type
for ( const auto& function : mgr.p1Functions_.getFunctions<double>() )
{
writeScalarFunction( output, function, storage, level, mgr.write2D_, mgr.vtkDataFormat_ );
}
for ( const auto& function : mgr.p1Functions_.getFunctions<int32_t>() )
{
writeScalarFunction( output, function, storage, level, mgr.write2D_, mgr.vtkDataFormat_ );
}
for ( const auto& function : mgr.p1Functions_.getFunctions<int64_t>() )
{
writeScalarFunction( output, function, storage, level, mgr.write2D_, mgr.vtkDataFormat_ );
}
......@@ -89,18 +98,17 @@ void VTKP1Writer::write( const VTKOutput& mgr, std::ostream& output, const uint_
vtk::writePieceFooter( output );
}
void VTKP1Writer::writeScalarFunction( std::ostream& output,
const vertexdof::VertexDoFFunction< real_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat )
template < typename value_t >
void VTKP1Writer::writeScalarFunction( std::ostream& output,
const vertexdof::VertexDoFFunction< value_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat )
{
using ScalarType = real_t;
VTKOutput::VTKStreamWriter< value_t > streamWriter( vtkDataFormat );
VTKOutput::VTKStreamWriter< ScalarType > streamWriter( vtkDataFormat );
vtk::openDataElement( output, typeToString< real_t >(), function.getFunctionName(), 1, vtkDataFormat );
vtk::openDataElement( output, typeToString< value_t >(), function.getFunctionName(), 1, vtkDataFormat );
if ( write2D )
{
......@@ -135,19 +143,18 @@ void VTKP1Writer::writeScalarFunction( std::ostream&
output << "\n</DataArray>\n";
}
template < typename value_t >
void VTKP1Writer::writeVectorFunction( std::ostream& output,
const P1VectorFunction< real_t >& function,
const P1VectorFunction< value_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat )
{
using ScalarType = real_t;
VTKOutput::VTKStreamWriter< ScalarType > streamWriter( vtkDataFormat );
VTKOutput::VTKStreamWriter< value_t > streamWriter( vtkDataFormat );
uint_t dim = write2D ? 2 : 3;
vtk::openDataElement( output, typeToString< real_t >(), function.getFunctionName(), dim, vtkDataFormat );
vtk::openDataElement( output, typeToString< value_t >(), function.getFunctionName(), dim, vtkDataFormat );
if ( write2D )
{
......
......@@ -31,19 +31,21 @@ class VTKP1Writer
static void write( const VTKOutput& mgr, std::ostream& output, const uint_t& level );
private:
static void writeScalarFunction( std::ostream& output,
const vertexdof::VertexDoFFunction< real_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat );
template< typename value_t >
static void writeScalarFunction( std::ostream& output,
const vertexdof::VertexDoFFunction< value_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat );
static void writeVectorFunction( std::ostream& output,
const P1VectorFunction< real_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat );
template< typename value_t >
static void writeVectorFunction( std::ostream& output,
const P1VectorFunction< value_t >& function,
const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
bool write2D,
vtk::DataFormat vtkDataFormat );
};
} // namespace hyteg
/*
* Copyright (c) 2021 Marcus Mohr.
*
* This file is part of HyTeG
* (see https://i10git.cs.fau.de/hyteg/hyteg).
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "core/DataTypes.h"
#include "hyteg/functions/FunctionProperties.hpp"
#include "hyteg/functions/FunctionWrapper.hpp"
namespace hyteg {
using walberla::uint_t;
/// Class for storing multiple functions from the same family but with (potentially) different value types
///
/// This class allows to store multiple functions from the same family, which can but need not differ in
/// their value types. The class is currently intended as a replacement for the std::vector< "func_t"< real_t >
/// containes in VTKOuput and thus tries to behave as much as possbile like an std::vector. Currently
/// supported value types are
/// - double
/// - float
/// - int32_t
/// - int64_t
/// Extension to other datatypes is straightforward.
template < template < class > class func_t >
class FunctionMultiStore
{
public:
template < typename value_t >
inline void push_back( const func_t< value_t >& function )
{
if constexpr ( std::is_same< value_t, double >::value )
{
r64Funcs.push_back( function );
}
else if constexpr ( std::is_same< value_t, float >::value )
{
r32Funcs.push_back( function );
}
else if constexpr ( std::is_same< value_t, int32_t >::value )
{
i32Funcs.push_back( function );
}
else if constexpr ( std::is_same< value_t, int64_t >::value )
{
i64Funcs.push_back( function );
}
else
{
WALBERLA_ABORT( "FunctionMultiStore::add() detected unsupported datatype '" << typeid( function ).name() << "'" );
};
};
uint_t size() const { return r64Funcs.size() + r32Funcs.size() + i32Funcs.size() + i64Funcs.size(); };
template < typename value_t >
const std::vector< func_t< value_t > >& getFunctions() const
{
if constexpr ( std::is_same< value_t, double >::value )
{
return r64Funcs;
}
else if constexpr ( std::is_same< value_t, float >::value )
{
return r32Funcs;
}
else if constexpr ( std::is_same< value_t, int >::value )
{
return i32Funcs;
}
else if constexpr ( std::is_same< value_t, long >::value )
{
return i64Funcs;
}
else
{
WALBERLA_ABORT( "FunctionMultiStore::getFunctions() detected unsupported datatype '" << typeid( value_t ).name() );
}
}
private:
std::vector< func_t< double > > r64Funcs;
std::vector< func_t< float > > r32Funcs;
std::vector< func_t< int32_t > > i32Funcs;
std::vector< func_t< int64_t > > i64Funcs;
};
} // namespace hyteg
......@@ -628,6 +628,9 @@ waLBerla_execute_test(NAME FunctionMemorySerializationTest1 COMMAND $<TARGET_FIL
waLBerla_execute_test(NAME FunctionMemorySerializationTest2 COMMAND $<TARGET_FILE:FunctionMemorySerializationTest> PROCESSES 2 )
waLBerla_execute_test(NAME FunctionMemorySerializationTest8 COMMAND $<TARGET_FILE:FunctionMemorySerializationTest> PROCESSES 8 )
waLBerla_compile_test(FILES functions/FunctionMultiStoreTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME FunctionMultiStoreTest)
waLBerla_compile_test(FILES blending/AnnulusMapTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME AnnulusMapTest1 COMMAND $<TARGET_FILE:AnnulusMapTest> )
......@@ -659,7 +662,6 @@ if( HYTEG_BUILD_WITH_PETSC )
waLBerla_execute_test(NAME ElementwiseOperatorPetscTest2 COMMAND $<TARGET_FILE:ElementwiseOperatorPetscTest> PROCESSES 2 )
endif()
# Test some basic auxiliary stuff for application layer
waLBerla_compile_test(FILES functions/FindMaxMinMagTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME FindMaxMinMagTest1 COMMAND $<TARGET_FILE:FindMaxMinMagTest> )
......
......@@ -68,6 +68,10 @@ static void exportFunctions2D()
p1VectorFunc.interpolate( vecExpr, maxLevel, DoFType::All );
p2VectorFunc.interpolate( vecExpr, maxLevel, DoFType::All );
// An integer function
P1Function< int > p1Enumerator( "int it is!", storage, minLevel, maxLevel );
p1Enumerator.enumerate( maxLevel );
// Output VTK
bool beVerbose = true;
if ( beVerbose )
......@@ -79,6 +83,7 @@ static void exportFunctions2D()
vtkOutput.add( p1ScalarFunc1 );
vtkOutput.add( p1ScalarFunc2 );
vtkOutput.add( p1VectorFunc );
vtkOutput.add( p1Enumerator );
vtkOutput.write( maxLevel );
fName = "VTKOutputTestP2";
......
/*
* Copyright (c) 2021 Marcus Mohr
*
* This file is part of HyTeG
* (see https://i10git.cs.fau.de/hyteg/hyteg).
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <vector>
#include "core/Environment.h"
#include "core/debug/CheckFunctions.h"
#include "core/debug/TestSubsystem.h"
#include "hyteg/mesh/MeshInfo.hpp"
#include "hyteg/primitivestorage/PrimitiveStorage.hpp"
#include "hyteg/primitivestorage/SetupPrimitiveStorage.hpp"
#include "hyteg/primitivestorage/loadbalancing/SimpleBalancer.hpp"
#include "hyteg/p1functionspace/P1Function.hpp"
#include "hyteg/p2functionspace/P2Function.hpp"
#include "hyteg/p2functionspace/P2VectorFunction.hpp"
#include "hyteg/functions/FunctionMultiStore.hpp"
using walberla::uint_t;
using namespace hyteg;
// --------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
walberla::debug::enterTestMode();
walberla::Environment walberlaEnv(argc, argv);
walberla::logging::Logging::instance()->setLogLevel( walberla::logging::Logging::PROGRESS );
walberla::MPIManager::instance()->useWorldComm();
uint_t theLevel = 3;
// Generate mesh around origin
MeshInfo meshInfo = MeshInfo::emptyMeshInfo();
meshInfo = MeshInfo::meshRectangle( Point2D( {0.0, 0.0} ), Point2D( {1.0, 1.0} ), MeshInfo::CROSS, 1, 1 );
// Generate primitives
SetupPrimitiveStorage setupStorage( meshInfo, uint_c ( walberla::mpi::MPIManager::instance()->numProcesses() ) );
loadbalancing::roundRobin( setupStorage );
std::shared_ptr<PrimitiveStorage> storage = std::make_shared<PrimitiveStorage>( setupStorage );
// =============
// P1Function
// =============
hyteg::P1Function< double > dFunc1( "#1", storage, theLevel, theLevel );
hyteg::P1Function< double > dFunc2( "#2", storage, theLevel, theLevel );
// hyteg::P1Function< float > fFunc1( "#3", storage, theLevel, theLevel );
hyteg::P1Function< int32_t > iFunc1( "#4", storage, theLevel, theLevel );
hyteg::P1Function< int64_t > lFunc1( "#5", storage, theLevel, theLevel );
FunctionMultiStore< P1Function > ms;
ms.push_back( dFunc1 );
ms.push_back( dFunc2 );
ms.push_back( iFunc1 );
ms.push_back( lFunc1 );
WALBERLA_LOG_INFO_ON_ROOT( "FunctionMultiStore holds " << ms.size() << " P1Functions" );
// ==================
// P2VectorFunction
// ==================
hyteg::P2VectorFunction< double > dVecFunc1( "#1", storage, theLevel, theLevel );
hyteg::P2VectorFunction< double > dVecFunc2( "#2", storage, theLevel, theLevel );
// hyteg::P2VectorFunction< float > fVecFunc1( "#3", storage, theLevel, theLevel );
hyteg::P2VectorFunction< int32_t > iVecFunc1( "#4", storage, theLevel, theLevel );
hyteg::P2VectorFunction< int64_t > lVecFunc1( "#5", storage, theLevel, theLevel );
hyteg::P2VectorFunction< int64_t > lVecFunc2( "#6", storage, theLevel, theLevel );
FunctionMultiStore< P2VectorFunction > ms2;
ms2.push_back( dVecFunc1 );
ms2.push_back( dVecFunc2 );
ms2.push_back( iVecFunc1 );
ms2.push_back( lVecFunc1 );
ms2.push_back( lVecFunc2 );
WALBERLA_LOG_INFO_ON_ROOT( "FunctionMultiStore holds " << ms2.size() << " P2VectorFunctions" );
// try obtaining a specific vector from the store
auto dFuncs = ms2.getFunctions< double >();
WALBERLA_LOG_INFO_ON_ROOT( " - of these " << dFuncs.size() << " have value type 'double'" );
auto iFuncs = ms2.getFunctions< int32_t >();
WALBERLA_LOG_INFO_ON_ROOT( " - of these " << iFuncs.size() << " have value type 'int32_t'" );
return EXIT_SUCCESS;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment