Commit 4815ce2f authored by Andreas Wagner's avatar Andreas Wagner
Browse files

adds DGFunction::copyFrom functions

parent 4200415e
......@@ -153,18 +153,12 @@ class DGFunction final : public Function< DGFunction< ValueType > >
uint_t level,
DoFType flag = All ) const;
void copyFrom( const DGFunction< ValueType >& other, const uint_t& level ) const
{
WALBERLA_ABORT( "DGFunction::copyFrom not implemented!" )
}
inline void copyFrom( const DGFunction< ValueType >& other, const uint_t& level ) const;
void copyFrom( const DGFunction< ValueType >& other,
const uint_t& level,
const std::map< PrimitiveID::IDType, uint_t >& localPrimitiveIDsToRank,
const std::map< PrimitiveID::IDType, uint_t >& otherPrimitiveIDsToRank ) const
{
WALBERLA_ABORT( "DGFunction::copyFrom not implemented!" )
}
inline void copyFrom( const DGFunction< ValueType >& other,
const uint_t& level,
const std::map< PrimitiveID::IDType, uint_t >& localPrimitiveIDsToRank,
const std::map< PrimitiveID::IDType, uint_t >& otherPrimitiveIDsToRank ) const;
void setBoundaryCondition( BoundaryCondition bc ){WALBERLA_ABORT( "DGFunction::setBoundaryCondition not implemented!" )}
......@@ -682,6 +676,11 @@ inline void DGFunction< ValueType >::swap( const DGFunction< ValueType >& other,
template < typename ValueType >
ValueType DGFunction< ValueType >::dotLocal( const DGFunction< ValueType >& secondOp, uint_t level, DoFType flag ) const
{
if ( this->getStorage()->hasGlobalCells() )
{
WALBERLA_ABORT( "DGFunction::dotLocal() not implemented for 3D!" );
}
this->startTiming( "Dot (local)" );
walberla::math::KahanAccumulator< ValueType > scalarProduct;
......@@ -731,4 +730,154 @@ ValueType DGFunction< ValueType >::dotGlobal( const DGFunction< ValueType >& sec
return scalarProduct;
}
template < typename ValueType >
void DGFunction< ValueType >::copyFrom( const DGFunction< ValueType >& other, const uint_t& level ) const
{
if ( this->getStorage()->hasGlobalCells() )
{
WALBERLA_ABORT( "DGFunction::copyFrom() not implemented for 3D!" );
}
this->startTiming( "Copy" );
for ( auto& it : this->getStorage()->getVertices() )
{
auto primitiveID = it.first;
WALBERLA_ASSERT( other.getStorage()->vertexExistsLocally( primitiveID ) )
this->getStorage()
->getVertex( primitiveID )
->getData( vertexDataID_ )
->copyFrom( *other.getStorage()->getVertex( primitiveID )->getData( other.getVertexDataID() ), level );
}
for ( auto& it : this->getStorage()->getEdges() )
{
auto primitiveID = it.first;
WALBERLA_ASSERT( other.getStorage()->edgeExistsLocally( primitiveID ) )
this->getStorage()
->getEdge( primitiveID )
->getData( edgeDataID_ )
->copyFrom( *other.getStorage()->getEdge( primitiveID )->getData( other.getEdgeDataID() ), level );
}
for ( auto& it : this->getStorage()->getFaces() )
{
auto primitiveID = it.first;
WALBERLA_ASSERT( other.getStorage()->faceExistsLocally( primitiveID ) )
this->getStorage()
->getFace( primitiveID )
->getData( faceDataID_ )
->copyFrom( *other.getStorage()->getFace( primitiveID )->getData( other.getFaceDataID() ), level );
}
this->stopTiming( "Copy" );
}
template < typename ValueType >
void DGFunction< ValueType >::copyFrom( const DGFunction< ValueType >& other,
const uint_t& level,
const std::map< PrimitiveID::IDType, uint_t >& localPrimitiveIDsToRank,
const std::map< PrimitiveID::IDType, uint_t >& otherPrimitiveIDsToRank ) const
{
if ( this->getStorage()->hasGlobalCells() )
{
WALBERLA_ABORT( "DGFunction::copyFrom() not implemented for 3D!" );
}
this->startTiming( "Copy" );
walberla::mpi::BufferSystem bufferSystem( walberla::mpi::MPIManager::instance()->comm(), 9563 );
std::set< walberla::mpi::MPIRank > receiverRanks;
for ( auto it : localPrimitiveIDsToRank )
{
receiverRanks.insert( walberla::mpi::MPIRank( it.second ) );
}
bufferSystem.setReceiverInfo( receiverRanks, true );
for ( auto& it : other.getStorage()->getVertices() )
{
PrimitiveID::IDType otherPrimitiveID = it.first;
WALBERLA_CHECK_GREATER( otherPrimitiveIDsToRank.count( otherPrimitiveID ), 0 );
auto otherData = it.second->getData( other.getVertexDataID() )->getPointer( level );
auto otherDataSize = it.second->getData( other.getVertexDataID() )->getSize( level );
auto targetRank = otherPrimitiveIDsToRank.at( otherPrimitiveID );
bufferSystem.sendBuffer( targetRank ) << otherPrimitiveID;
bufferSystem.sendBuffer( targetRank ) << uint_c( 0 );
bufferSystem.sendBuffer( targetRank ) << otherDataSize;
for ( uint_t i = 0; i < otherDataSize; i++ )
bufferSystem.sendBuffer( targetRank ) << otherData[i];
}
for ( auto& it : other.getStorage()->getEdges() )
{
PrimitiveID::IDType otherPrimitiveID = it.first;
WALBERLA_CHECK_GREATER( otherPrimitiveIDsToRank.count( otherPrimitiveID ), 0 );
auto otherData = it.second->getData( other.getEdgeDataID() )->getPointer( level );
auto otherDataSize = it.second->getData( other.getEdgeDataID() )->getSize( level );
auto targetRank = otherPrimitiveIDsToRank.at( otherPrimitiveID );
bufferSystem.sendBuffer( targetRank ) << otherPrimitiveID;
bufferSystem.sendBuffer( targetRank ) << uint_c( 1 );
bufferSystem.sendBuffer( targetRank ) << otherDataSize;
for ( uint_t i = 0; i < otherDataSize; i++ )
bufferSystem.sendBuffer( targetRank ) << otherData[i];
}
for ( auto& it : other.getStorage()->getFaces() )
{
PrimitiveID::IDType otherPrimitiveID = it.first;
WALBERLA_CHECK_GREATER( otherPrimitiveIDsToRank.count( otherPrimitiveID ), 0 );
auto otherData = it.second->getData( other.getFaceDataID() )->getPointer( level );
auto otherDataSize = it.second->getData( other.getFaceDataID() )->getSize( level );
auto targetRank = otherPrimitiveIDsToRank.at( otherPrimitiveID );
bufferSystem.sendBuffer( targetRank ) << otherPrimitiveID;
bufferSystem.sendBuffer( targetRank ) << uint_c( 2 );
bufferSystem.sendBuffer( targetRank ) << otherDataSize;
for ( uint_t i = 0; i < otherDataSize; i++ )
bufferSystem.sendBuffer( targetRank ) << otherData[i];
}
bufferSystem.sendAll();
for ( auto pkg = bufferSystem.begin(); pkg != bufferSystem.end(); ++pkg )
{
while ( !pkg.buffer().isEmpty() )
{
PrimitiveID::IDType otherID;
uint_t primitiveType = 4;
uint_t dataSize = 0;
ValueType value;
ValueType* dstPointer;
pkg.buffer() >> otherID;
pkg.buffer() >> primitiveType;
pkg.buffer() >> dataSize;
WALBERLA_CHECK( this->getStorage()->primitiveExistsLocally( PrimitiveID( otherID ) ) );
switch ( primitiveType )
{
case 0:
dstPointer = this->getStorage()->getVertex( PrimitiveID( otherID ) )->getData( vertexDataID_ )->getPointer( level );
break;
case 1:
dstPointer = this->getStorage()->getEdge( PrimitiveID( otherID ) )->getData( edgeDataID_ )->getPointer( level );
break;
case 2:
dstPointer = this->getStorage()->getFace( PrimitiveID( otherID ) )->getData( faceDataID_ )->getPointer( level );
break;
default:
WALBERLA_ABORT( "Invalid primitive type" )
}
for ( uint_t i = 0; i < dataSize; i++ )
{
pkg.buffer() >> value;
dstPointer[i] = value;
}
}
}
this->stopTiming( "Copy" );
}
} // namespace hyteg
......@@ -517,6 +517,9 @@ waLBerla_execute_test(NAME DGSwapTest)
waLBerla_compile_test(FILES DGDotTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME DGDotTest)
waLBerla_compile_test(FILES DGCopyFromTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME DGCopyFromTest)
waLBerla_compile_test(FILES vCycleTest.cpp DEPENDS hyteg core)
waLBerla_execute_test(NAME vCycleTest1 COMMAND $<TARGET_FILE:vCycleTest> )
......
/*
* Copyright (c) 2021 Andreas Wagner.
*
* 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 "core/debug/all.h"
#include "core/mpi/all.h"
#include "hyteg/dataexport/VTKOutput.hpp"
#include "hyteg/dgfunctionspace/DGFunction.hpp"
#include "hyteg/mesh/MeshInfo.hpp"
#include "hyteg/primitivestorage/PrimitiveStorage.hpp"
#include "hyteg/primitivestorage/SetupPrimitiveStorage.hpp"
#include "hyteg/primitivestorage/loadbalancing/SimpleBalancer.hpp"
using namespace hyteg;
using walberla::real_t;
int main( int argc, char** argv )
{
walberla::mpi::Environment MPIenv( argc, argv );
walberla::MPIManager::instance()->useWorldComm();
walberla::debug::enterTestMode();
MeshInfo meshInfo = MeshInfo::meshRectangle( Point2D( { 0, 0 } ), Point2D( { 1, 1 } ), MeshInfo::CRISS, 1, 1 );
SetupPrimitiveStorage setupStorage( meshInfo, uint_c( walberla::mpi::MPIManager::instance()->numProcesses() ) );
std::shared_ptr< PrimitiveStorage > storage1 = std::make_shared< PrimitiveStorage >( setupStorage );
std::shared_ptr< PrimitiveStorage > storage2 = std::make_shared< PrimitiveStorage >( setupStorage );
const uint_t minLevel = 2;
const uint_t maxLevel = 4;
hyteg::DGFunction< real_t > x1( "x1", storage1, minLevel, maxLevel );
hyteg::DGFunction< real_t > x2( "x2", storage2, minLevel, maxLevel );
x1.interpolate(1, maxLevel, All);
x2.copyFrom(x1, maxLevel);
// check if copying worked:
WALBERLA_CHECK_FLOAT_EQUAL( x2.getMinValue( maxLevel, All ), 1. );
WALBERLA_CHECK_FLOAT_EQUAL( x2.getMaxValue( maxLevel, All ), 1. );
// check that it is a copy and changing x1 has no impact on x2:
x1.interpolate(0, maxLevel, All);
WALBERLA_CHECK_FLOAT_EQUAL( x2.getMinValue( maxLevel, All ), 1. );
WALBERLA_CHECK_FLOAT_EQUAL( x2.getMaxValue( maxLevel, All ), 1. );
WALBERLA_CHECK_FLOAT_EQUAL( x1.getMinValue( maxLevel, All ), 0. );
WALBERLA_CHECK_FLOAT_EQUAL( x1.getMaxValue( maxLevel, All ), 0. );
return 0;
}
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