Commit b7d9cc47 authored by Tobias Schruff's avatar Tobias Schruff

Merge remote-tracking branch 'upstream'

parents d09f67dc cd7d2c52
Pipeline #8174 failed with stage
in 59 minutes and 11 seconds
###############################################################################
## ##
## Genral settings ##
## General settings ##
## ##
###############################################################################
......@@ -970,6 +970,71 @@ msvc-14.1_MpiOnly:
- triggers
###############################################################################
## ##
## macOS Builds ##
## ##
###############################################################################
.mac_build_template: &mac_build_definition
script:
- export NUM_CORES=$(system_profiler SPHardwareDataType | grep 'Total Number of Cores' | awk '{print $5}')
- export MAX_BUILD_CORES=$(( $(system_profiler SPHardwareDataType | grep 'Memory' | awk '{print $2}') / 4 ))
- "[[ $MAX_BUILD_CORES -lt $NUM_CORES ]] && export NUM_BUILD_CORES=$MAX_BUILD_CORES || export NUM_BUILD_CORES=$NUM_CORES"
- c++ --version
- cmake --version
- mpirun --version
- mkdir build
- cd build
- cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DWARNING_ERROR=ON
- cmake . -LAH
- make -j $NUM_BUILD_CORES -l $NUM_CORES
- ctest -LE "$CTEST_EXCLUDE_LABELS|cuda" -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES
tags:
- mac
mac_Serial_Dbg:
<<: *mac_build_definition
variables:
CMAKE_BUILD_TYPE: "DebugOptimized"
CTEST_EXCLUDE_LABELS: "longrun"
WALBERLA_BUILD_WITH_MPI: "OFF"
WALBERLA_BUILD_WITH_OPENMP: "OFF"
WALBERLA_BUILD_WITH_PYTHON: "ON"
WALBERLA_BUILD_WITH_CUDA: "ON"
mac_Serial:
<<: *mac_build_definition
variables:
CMAKE_BUILD_TYPE: "Release"
CTEST_EXCLUDE_LABELS: "longrun"
WALBERLA_BUILD_WITH_MPI: "OFF"
WALBERLA_BUILD_WITH_OPENMP: "OFF"
WALBERLA_BUILD_WITH_PYTHON: "ON"
WALBERLA_BUILD_WITH_CUDA: "ON"
mac_MpiOnly_Dbg:
<<: *mac_build_definition
variables:
CMAKE_BUILD_TYPE: "DebugOptimized"
CTEST_EXCLUDE_LABELS: "longrun"
WALBERLA_BUILD_WITH_MPI: "ON"
WALBERLA_BUILD_WITH_OPENMP: "OFF"
WALBERLA_BUILD_WITH_PYTHON: "ON"
WALBERLA_BUILD_WITH_CUDA: "ON"
mac_MpiOnly:
<<: *mac_build_definition
variables:
CMAKE_BUILD_TYPE: "Release"
CTEST_EXCLUDE_LABELS: "longrun"
WALBERLA_BUILD_WITH_MPI: "ON"
WALBERLA_BUILD_WITH_OPENMP: "OFF"
WALBERLA_BUILD_WITH_PYTHON: "ON"
WALBERLA_BUILD_WITH_CUDA: "ON"
###############################################################################
## ##
## Deploy jobs ##
......
......@@ -360,17 +360,6 @@ if( NOT WARNING_DEPRECATED)
endif()
endif()
# Treat warnings as errors
if ( WARNING_ERROR )
if( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL OR WALBERLA_CXX_COMPILER_IS_CLANG )
add_flag ( CMAKE_CXX_FLAGS "-pedantic-errors -Werror" )
elseif( WALBERLA_CXX_COMPILER_IS_MSVC )
add_flag ( CMAKE_CXX_FLAGS "/WX" )
elseif ( WALBERLA_CXX_COMPILER_IS_CRAY )
add_flag ( CMAKE_CXX_FLAGS "-h error_on_warning" )
endif()
endif ( )
if ( WALBERLA_CXX_COMPILER_IS_CLANG )
add_flag ( CMAKE_CXX_FLAGS "-Wall -Wconversion -Wshadow -Wno-c++11-extensions -Qunused-arguments" )
......@@ -784,18 +773,16 @@ if ( WALBERLA_BUILD_WITH_MPI AND NOT WALBERLA_CXX_COMPILER_IS_MPI_WRAPPER )
if ( WIN32 )
message ( STATUS "Enter Workaround Routine for Windows and OpenMPI: PRESS CONFIGURE ONE MORE TIME!" )
string ( REGEX REPLACE "(.*)/bin/.*" "\\1" MPI_PATH ${MPI_CXX_COMPILER} )
find_path ( MPI_INCLUDE_PATH mpi.h
find_path ( MPI_C_INCLUDE_PATH mpi.h
HINTS ${MPI_PATH}
PATH_SUFFIXES include Inc)
set ( MPI_CXX_INCLUDE_PATH ${MPI_INCLUDE_PATH} CACHE FILEPATH "" FORCE )
set ( MPI_C_INCLUDE_PATH ${MPI_INCLUDE_PATH} CACHE FILEPATH "" FORCE )
set ( MPI_CXX_INCLUDE_PATH ${MPI_C_INCLUDE_PATH} CACHE FILEPATH "" FORCE )
set ( MPI_CXX_LIBRARIES "MPI_CXX_LIBRARIES-NOTFOUND" CACHE FILEPATH "Cleared" FORCE )
find_library ( MPI_CXX_LIBRARIES
NAMES mpi++ mpicxx cxx mpi_cxx libmpi++ libmpicxx libcxx libmpi_cxx
HINTS ${MPI_PATH}
PATH_SUFFIXES lib )
set ( MPI_LIBRARY "MPI_CXX_LIBRARIES" CACHE FILEPATH "" FORCE )
if ( NOT MPI_CXX_LIBRARIES STREQUAL "MPI_CXX_LIBRARIES-NOTFOUND" )
set ( MPI_CXX_FOUND ON FORCE )
......@@ -806,7 +793,6 @@ if ( WALBERLA_BUILD_WITH_MPI AND NOT WALBERLA_CXX_COMPILER_IS_MPI_WRAPPER )
NAMES mpi mpich mpich2 msmpi libmpi libmpich libmpich2 libmsmpi
HINTS ${MPI_PATH}
PATH_SUFFIXES lib )
set ( MPI_EXTRA_LIBRARY "MPI_C_LIBRARIES" CACHE FILEPATH "" FORCE )
if ( NOT MPI_C_LIBRARIES STREQUAL "MPI_C_LIBRARIES-NOTFOUND" )
set ( MPI_C_FOUND ON FORCE )
......@@ -823,23 +809,14 @@ if ( WALBERLA_BUILD_WITH_MPI AND NOT WALBERLA_CXX_COMPILER_IS_MPI_WRAPPER )
endif ( )
if ( MPI_FOUND )
if ( MPI_CXX_FOUND )
include_directories ( SYSTEM ${MPI_CXX_INCLUDE_PATH} ${MPI_C_INCLUDE_PATH} )
foreach( LIB ${MPI_C_LIBRARIES} ${MPI_CXX_LIBRARIES} )
if ( LIB )
list ( APPEND SERVICE_LIBS ${LIB} )
endif ( )
endforeach ( )
add_flag ( CMAKE_CXX_FLAGS "${MPI_CXX_COMPILE_FLAGS}" )
add_flag ( CMAKE_C_FLAGS "${MPI_C_COMPILE_FLAGS}" )
else ( ) # For older CMake versions
include_directories ( SYSTEM ${MPI_INCLUDE_PATH} )
list ( APPEND SERVICE_LIBS ${MPI_LIBRARY} )
if ( MPI_EXTRA_LIBRARY )
list ( APPEND SERVICE_LIBS ${MPI_EXTRA_LIBRARY} )
include_directories ( SYSTEM ${MPI_CXX_INCLUDE_PATH} ${MPI_C_INCLUDE_PATH} )
foreach( LIB ${MPI_C_LIBRARIES} ${MPI_CXX_LIBRARIES} )
if ( LIB )
list ( APPEND SERVICE_LIBS ${LIB} )
endif ( )
add_flag ( CMAKE_C_FLAGS "${MPI_COMPILE_FLAGS}" )
endif ( )
endforeach ( )
add_flag ( CMAKE_CXX_FLAGS "${MPI_CXX_COMPILE_FLAGS}" )
add_flag ( CMAKE_C_FLAGS "${MPI_C_COMPILE_FLAGS}" )
add_flag ( CMAKE_MODULE_LINKER_FLAGS "${MPI_CXX_LINK_FLAGS}" )
add_flag ( CMAKE_EXE_LINKER_FLAGS "${MPI_CXX_LINK_FLAGS}" )
......@@ -847,7 +824,7 @@ if ( WALBERLA_BUILD_WITH_MPI AND NOT WALBERLA_CXX_COMPILER_IS_MPI_WRAPPER )
# When using Intel MPI, mpi.h has to be included before including the standard library
# therefore we use the -include flag to enforce this.
if ( MPI_INCLUDE_PATH MATCHES "intel" )
if ( MPI_C_INCLUDE_PATH MATCHES "intel" )
message (STATUS "Activating IntelMPI include workaround for mpi.h" )
add_flag ( CMAKE_CXX_FLAGS "-include mpi.h" )
add_flag ( CMAKE_C_FLAGS "-include mpi.h" )
......@@ -1233,7 +1210,23 @@ if ( WALBERLA_BUILD_WITH_LTO )
endif( )
endif ( )
############################################################################################################################
##
## Some more compiler flags that need to happen after any try_compile (e.g. inside FindMPI)
##
############################################################################################################################
# Treat warnings as errors
if ( WARNING_ERROR )
if( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL OR WALBERLA_CXX_COMPILER_IS_CLANG )
add_flag ( CMAKE_CXX_FLAGS "-pedantic-errors -Werror" )
elseif( WALBERLA_CXX_COMPILER_IS_MSVC )
add_flag ( CMAKE_CXX_FLAGS "/WX" )
elseif ( WALBERLA_CXX_COMPILER_IS_CRAY )
add_flag ( CMAKE_CXX_FLAGS "-h error_on_warning" )
endif()
endif ( )
############################################################################################################################
##
......
......@@ -156,6 +156,11 @@ function ( waLBerla_export )
# Export link paths
set ( WALBERLA_LINK_DIRS ${LINK_DIRS} CACHE INTERNAL "waLBerla link directories" )
set( WALBERLA_CXX_STANDARD ${CMAKE_CXX_STANDARD} CACHE INTERNAL "CXX standard")
set( WALBERLA_CXX_STANDARD_REQUIRED ${CMAKE_CXX_STANDARD_REQUIRED} CACHE INTERNAL "CXX Standard Required")
set( WALBERLA_CXX_EXTENSIONS ${CMAKE_CXX_EXTENSIONS} CACHE INTERNAL "CXX Extensions")
endfunction( waLBerla_export)
#######################################################################################################################
......@@ -210,7 +215,11 @@ function ( waLBerla_import )
endif()
set( SERVICE_LIBS ${WALBERLA_SERVICE_LIBS} PARENT_SCOPE )
set( CMAKE_CXX_STANDARD ${WALBERLA_CXX_STANDARD} PARENT_SCOPE)
set( CMAKE_CXX_STANDARD_REQUIRED ${WALBERLA_STANDARD_REQUIRED} PARENT_SCOPE)
set( CMAKE_CXX_EXTENSIONS ${WALBERLA_EXTENSIONS} PARENT_SCOPE)
link_directories( ${WALBERLA_LINK_DIRS} )
endfunction( waLBerla_import)
#######################################################################################################################
......
......@@ -23,10 +23,12 @@
#include "blockforest/PhantomBlockForest.h"
#include "core/debug/Debug.h"
#include "core/DataTypes.h"
#include "core/math/Vector3.h"
#include "core/mpi/MPIWrapper.h"
#include <cmath>
#include <map>
namespace walberla {
......@@ -40,7 +42,7 @@ std::map< blockforest::BlockID, uint_t > getBlockIdToSequenceMapping( const Phan
class DynamicParMetis
{
public:
enum Algorithm { PARMETIS_PART_GEOM_KWAY, PARMETIS_PART_KWAY, PARMETIS_ADAPTIVE_REPART, PARMETIS_REFINE_KWAY };
enum Algorithm { PARMETIS_PART_GEOM, PARMETIS_PART_GEOM_KWAY, PARMETIS_PART_KWAY, PARMETIS_ADAPTIVE_REPART, PARMETIS_REFINE_KWAY };
enum WeightsToUse { PARMETIS_NO_WEIGHTS = 0, PARMETIS_EDGE_WEIGHTS = 1, PARMETIS_VERTEX_WEIGHTS = 2, PARMETIS_BOTH_WEIGHTS = 3 };
enum EdgeSource { PARMETIS_EDGES_FROM_FOREST, PARMETIS_EDGES_FROM_EDGE_WEIGHTS };
......@@ -54,6 +56,10 @@ public:
const PhantomBlockForest & phantomForest,
const uint_t iteration ) const;
void setipc2redist(double val) {ipc2redist_ = val;}
double getipc2redist() const {return ipc2redist_;}
bool edgeWeightsUsed() const { return ( weightsToUse_ == PARMETIS_EDGE_WEIGHTS ) || ( weightsToUse_ == PARMETIS_BOTH_WEIGHTS ); }
bool vertexWeightsUsed() const { return ( weightsToUse_ == PARMETIS_VERTEX_WEIGHTS ) || ( weightsToUse_ == PARMETIS_BOTH_WEIGHTS ); }
bool vertexSizeUsed() const { return algorithm_ == PARMETIS_ADAPTIVE_REPART; }
......@@ -62,10 +68,16 @@ public:
static WeightsToUse stringToWeightsToUse( std::string s );
static EdgeSource stringToEdgeSource( std::string s );
std::string algorithmToString() const;
std::string weightsToUseToString() const;
std::string edgeSourceToString() const;
protected:
Algorithm algorithm_;
WeightsToUse weightsToUse_;
EdgeSource edgeSource_;
double ipc2redist_ = real_t( 1000.0 ); ///< compute repartitioning with low edge cut (set lower (down to 0.000001) to get minimal repartitioning )
};
class DynamicParMetisBlockInfo
......@@ -90,7 +102,7 @@ public:
vsize_t getVertexSize() const { return vertexSize_; }
void setVertexSize( const vsize_t size ) { vertexSize_ = size; }
const Vector3<double> & getVertexCoords() const { return vertexCoords_; }
const Vector3<double> & getVertexCoords() const { WALBERLA_ASSERT( !std::isnan(vertexCoords_[0]) && !std::isnan(vertexCoords_[1]) && !std::isnan(vertexCoords_[2]) ); return vertexCoords_; }
void setVertexCoords( const Vector3<double> & p ) { vertexCoords_ = p; }
void setEdgeWeight( const blockforest::BlockID & blockId, const weight_t edgeWeight ) { edgeWeights_[blockId] = edgeWeight; }
......@@ -107,7 +119,7 @@ private:
weight_t vertexWeight_; /// Defines the weight of a block
vsize_t vertexSize_; /// Defines the cost of rebalancing a block
Vector3<double> vertexCoords_; /// Defines where the block is located in space. Needed by some ParMetis algorithms
Vector3<double> vertexCoords_ = Vector3<double>(std::numeric_limits<double>::signaling_NaN()); /// Defines where the block is located in space. Needed by some ParMetis algorithms
std::map< blockforest::BlockID, weight_t > edgeWeights_; /// Defines the cost of communication with other blocks
};
......
......@@ -20,28 +20,67 @@
#include "MPIHelper.h"
#include <core/debug/CheckFunctions.h>
namespace walberla {
namespace mpi {
//!
//! \brief This functions maps the rank in one communicator to the rank in another communicator.
//! \param srcComm source communicator
//! \param destComm destination communicator
//! \param srcRank rank in the source communicator
//! \return rank in the destination communicator or -1 if not available
//!
int translateRank(const MPI_Comm srcComm, const MPI_Comm destComm, const int srcRank)
{
if (srcComm == destComm)
{
return srcRank;
}
int destRank = -1;
MPI_Group srcGroup, destGroup;
MPI_Comm_group(srcComm, &srcGroup);
MPI_Comm_group(destComm, &destGroup);
MPI_Group_translate_ranks(srcGroup, 1, const_cast<int*>(&srcRank), destGroup, &destRank);
int size;
MPI_Comm_size(destComm, &size);
if (destRank == MPI_UNDEFINED) destRank = -1;
WALBERLA_CHECK_GREATER_EQUAL(destRank, -1);
WALBERLA_CHECK_LESS(destRank, size);
MPI_Group_free(&srcGroup);
MPI_Group_free(&destGroup);
return destRank;
}
//!
//! \brief This functions converts a array of ranks in one communicator to an array of ranks in another communicator.
//! \param srcComm source communicator
//! \param destComm destination communicator
//! \param srcRank source ranks
//! \return converted ranks, -1 if not available
//!
std::vector<int> translateRank(const MPI_Comm srcComm, const MPI_Comm destComm, const std::vector<int>& srcRank)
{
if (srcComm == destComm)
{
return srcRank;
}
std::vector<int> destRank(srcRank.size(), -1);
MPI_Group srcGroup, destGroup;
MPI_Comm_group(srcComm, &srcGroup);
MPI_Comm_group(destComm, &destGroup);
MPI_Group_translate_ranks(srcGroup, int_c(srcRank.size()), const_cast<int*>(&srcRank[0]), destGroup, &destRank[0]);
int size;
MPI_Comm_size(destComm, &size);
for (auto& dstRnk : destRank)
{
if (dstRnk == MPI_UNDEFINED) dstRnk = -1;
WALBERLA_CHECK_GREATER_EQUAL(dstRnk, -1);
WALBERLA_CHECK_LESS(dstRnk, size);
}
MPI_Group_free(&srcGroup);
MPI_Group_free(&destGroup);
return destRank;
......
......@@ -35,26 +35,38 @@ public:
typedef blockforest::DynamicParMetisBlockInfo PhantomBlockWeight;
typedef blockforest::DynamicParMetisBlockInfoPackUnpack PhantomBlockWeightPackUnpackFunctor;
MetisAssignmentFunctor( const shared_ptr<InfoCollection>& ic ) : ic_( ic )
{}
MetisAssignmentFunctor( shared_ptr<InfoCollection>& ic, const real_t baseWeight = real_t(10.0) ) : ic_(ic), baseWeight_(baseWeight) {}
void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & )
{
for( auto it = blockData.begin(); it != blockData.end(); ++it )
{
const uint_t& weight = ic_->find( it->first->getId() )->second.numberOfLocalBodies;
blockforest::DynamicParMetisBlockInfo info( int64_c(weight) );
info.setVertexSize(int64_c( weight ));
const double weight = double_c( ic_->find( it->first->getId() )->second.numberOfLocalBodies ) + baseWeight_;
//const double commWeight = double_c( edgeWeightFactor * (double_c(ic_->find( it->first->getId() )->second.numberOfShadowBodies) + baseWeight_)) + 1;
blockforest::DynamicParMetisBlockInfo info( 0 );
info.setVertexWeight( int64_c(weight) );
info.setVertexSize( int64_c( weight ) );
info.setVertexCoords( it->first->getAABB().center() );
for( uint_t nb = uint_t(0); nb < it->first->getNeighborhoodSize(); ++nb )
{
info.setEdgeWeight(it->first->getNeighborId(nb), int64_c(weight) );
info.setEdgeWeight(it->first->getNeighborId(nb), int64_c(edgeWeight_) );
}
it->second = info;
}
}
inline void setBaseWeight( const double weight) { baseWeight_ = weight;}
inline double getBaseWeight() const { return baseWeight_; }
inline void setEdgeWeight( const double weight) { edgeWeight_ = weight;}
inline double getEdgeWeight() const { return edgeWeight_; }
private:
shared_ptr< InfoCollection > ic_;
///Base weight due to allocated data structures. A weight of zero for blocks is dangerous as empty blocks might accumulate on one process!
double baseWeight_ = 10.0;
double edgeWeight_ = 1.0;
};
}
......
......@@ -79,7 +79,7 @@ private:
size_t numberOfContactsTreated_;
};
class DEM : public DEMSolver<IntegrateImplictEuler, ResolveContactSpringDashpotHaffWerner>
class DEM : public DEMSolver<IntegrateImplicitEuler, ResolveContactSpringDashpotHaffWerner>
{
public:
DEM( const shared_ptr<BodyStorage>& globalBodyStorage
......@@ -88,8 +88,8 @@ public:
, domain_decomposition::BlockDataID ccdID
, domain_decomposition::BlockDataID fcdID
, WcTimingTree* tt = NULL)
: DEMSolver<IntegrateImplictEuler, ResolveContactSpringDashpotHaffWerner>(
IntegrateImplictEuler(), ResolveContactSpringDashpotHaffWerner(),
: DEMSolver<IntegrateImplicitEuler, ResolveContactSpringDashpotHaffWerner>(
IntegrateImplicitEuler(), ResolveContactSpringDashpotHaffWerner(),
globalBodyStorage, blockStorage, storageID, ccdID, fcdID, tt )
{
}
......
......@@ -128,7 +128,7 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt )
WALBERLA_ASSERT( bodyIt->checkInvariants(), "Invalid body state detected" );
WALBERLA_ASSERT( !bodyIt->hasSuperBody(), "Invalid superordinate body detected" );
// Moving the capsule according to the acting forces (don't move a sleeping capsule)
// Moving the body according to the acting forces (don't move a sleeping body)
if( bodyIt->isAwake() && !bodyIt->hasInfiniteMass() )
{
integrate_( *bodyIt, dt, *this );
......@@ -138,7 +138,7 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt )
bodyIt->resetForceAndTorque();
// Checking the state of the rigid body
WALBERLA_ASSERT( bodyIt->checkInvariants(), "Invalid capsule state detected" );
WALBERLA_ASSERT( bodyIt->checkInvariants(), "Invalid body state detected" );
// Resetting the acting forces
bodyIt->resetForceAndTorque();
......
......@@ -30,7 +30,7 @@ namespace pe {
namespace cr {
//*************************************************************************************************
/*!\brief Integrate the trajectory of one body using implict Euler.
/*!\brief Integrate the trajectory of one body using implicit Euler.
*
* \param id Body ID.
* \param dt Time step size.
......@@ -40,7 +40,7 @@ namespace cr {
* The implicit Euler algorithm, also known as backward Euler, is used. It is a first-order
* integrator that does conserves energy (i.e. it is symplectic.)
*/
class IntegrateImplictEuler {
class IntegrateImplicitEuler {
public:
void operator()( BodyID id, real_t dt, ICR & solver ) const
{
......@@ -72,7 +72,7 @@ public:
// Setting the axis-aligned bounding box
id->calcBoundingBox();
// Calculating the current motion of the capsule
// Calculating the current motion of the body
id->calcMotion();
}
};
......@@ -88,7 +88,7 @@ public:
* The explicit Euler algorithm, also known as forward Euler, is used. It is a first-order
* integrator that does not conserve energy (i.e. it is not symplectic.)
*/
class IntegrateExplictEuler {
class IntegrateExplicitEuler {
public:
void operator()( BodyID id, real_t dt, ICR & solver ) const
{
......@@ -120,7 +120,7 @@ public:
// Setting the axis-aligned bounding box
id->calcBoundingBox();
// Calculating the current motion of the capsule
// Calculating the current motion of the body
id->calcMotion();
}
};
......
......@@ -61,14 +61,14 @@ private:
WcTimingTree* tt_;
};
class PlainIntegrator : public PlainIntegratorSolver<IntegrateImplictEuler>
class PlainIntegrator : public PlainIntegratorSolver<IntegrateImplicitEuler>
{
public:
PlainIntegrator( const shared_ptr<BodyStorage>& globalBodyStorage
, const shared_ptr<BlockStorage>& blockStorage
, domain_decomposition::BlockDataID storageID
, WcTimingTree* tt = NULL)
: PlainIntegratorSolver<IntegrateImplictEuler>( IntegrateImplictEuler(), globalBodyStorage, blockStorage,
: PlainIntegratorSolver<IntegrateImplicitEuler>( IntegrateImplicitEuler(), globalBodyStorage, blockStorage,
storageID, tt )
{
}
......
......@@ -65,14 +65,14 @@ void PlainIntegratorSolver<Integrator>::timestep( const real_t dt )
BodyStorage& localStorage = (*storage)[0];
for (auto bd = localStorage.begin(); bd != localStorage.end(); ++bd){
// Checking the state of the body
WALBERLA_ASSERT( bd->checkInvariants(), "Invalid capsule state detected" );
WALBERLA_ASSERT( bd->checkInvariants(), "Invalid body state detected" );
WALBERLA_ASSERT( !bd->hasSuperBody(), "Invalid superordinate body detected" );
// Resetting the contact node and removing all attached contacts
// bd->resetNode();
bd->clearContacts();
// Moving the capsule according to the acting forces (don't move a sleeping capsule)
// Moving the body according to the acting forces (don't move a sleeping body)
if( bd->isAwake() && !bd->hasInfiniteMass() ) {
integrate_( *bd, dt, *this );
}
......@@ -80,8 +80,8 @@ void PlainIntegratorSolver<Integrator>::timestep( const real_t dt )
// Resetting the acting forces
bd->resetForceAndTorque();
// Checking the state of the capsule
WALBERLA_ASSERT( bd->checkInvariants(), "Invalid capsule state detected" );
// Checking the state of the body
WALBERLA_ASSERT( bd->checkInvariants(), "Invalid body state detected" );
}
}
if (tt_!=NULL) tt_->stop("Integrate Bodies");
......
......@@ -56,7 +56,7 @@ namespace pe {
CylindricalBoundary::CylindricalBoundary( id_t sid, id_t uid, const Vec3& gpos, const real_t radius,
MaterialID material )
: GeomPrimitive( getStaticTypeID(), sid, uid, material ) // Initializing the base object
, radius_(radius) // Radius of the cylinder // Length of the capsule
, radius_(radius) // Radius of the cylinder
{
//boundaries are always considered locally and have infinite mass
setGlobal( true );
......@@ -66,11 +66,11 @@ CylindricalBoundary::CylindricalBoundary( id_t sid, id_t uid, const Vec3& gpos,
// Checking the radius
// Since the constructor is never directly called but only used in a small number
// of functions that already check the capsule arguments, only asserts are used here to
// of functions that already check the cylinder arguments, only asserts are used here to
// double check the arguments.
WALBERLA_ASSERT_GREATER( radius, real_t(0), "Invalid capsule radius" );
WALBERLA_ASSERT_GREATER( radius, real_t(0), "Invalid cylinder radius" );
// Initializing the instantiated capsule
// Initializing the instantiated cylinder
gpos_ = gpos;
q_ = Quat(); // Setting the orientation
R_ = q_.toRotationMatrix(); // Setting the rotation matrix
......
......@@ -175,7 +175,7 @@ inline id_t CylindricalBoundary::getStaticTypeID()
//=================================================================================================
//*************************************************************************************************
/*!\name Capsule operators */
/*!\name Cylinder operators */
//@{
std::ostream& operator<<( std::ostream& os, const CylindricalBoundary& cb );
std::ostream& operator<<( std::ostream& os, CylindricalBoundaryID cb );
......
......@@ -75,11 +75,9 @@ void Manager::addPath( const std::string & path )
{
WALBERLA_ASSERT( initialized_ );
object main_module = import("__main__");
dict globals = extract<dict>( main_module.attr( "__dict__" ) );
exec( "import sys", globals );
std::string pathCommand = std::string ( "sys.path.append( \"") + path + "\" ) ";
exec( str(pathCommand), globals );
object sys = import("sys");
list sys_path = extract<list>( sys.attr("path") );
sys_path.append(path);
}
void Manager::triggerInitialization()
......@@ -116,10 +114,24 @@ void Manager::triggerInitialization()
}
catch ( boost::python::error_already_set & ) {
PyErr_Print();
PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
if( type_ptr )
{
extract<std::string> type_str(( str( handle<>( type_ptr ) ) ));
if( type_str.check() )
WALBERLA_LOG_DEVEL( type_str() );
}
if(value_ptr)
{
extract<std::string> value_str(( str( handle<>( value_ptr ) ) ));
if ( value_str.check() )
WALBERLA_LOG_DEVEL( value_str() );
}
WALBERLA_ABORT( "Error while initializing Python" );
}
}
......@@ -159,4 +171,3 @@ int someSymbolSoThatLinkerDoesNotComplain=0;
......@@ -31,6 +31,8 @@
#cmakedefine WALBERLA_BUILD_WITH_CUDA
#cmakedefine WALBERLA_BUILD_WITH_CODEGEN
#cmakedefine WALBERLA_BUFFER_DEBUG
#cmakedefine WALBERLA_THREAD_SAFE_LOGGING
......
......@@ -69,6 +69,11 @@ waLBerla_execute_test( NAME PE_OVERLAP )
waLBerla_compile_test( NAME PE_PARALLELEQUIVALENCE FILES ParallelEquivalence.cpp DEPENDS core blockforest )
waLBerla_execute_test( NAME PE_PARALLELEQUIVALENCE PROCESSES 4 )
if( WALBERLA_BUILD_WITH_PARMETIS )
waLBerla_compile_test( NAME PE_PARMETIS FILES ParMetis.cpp DEPENDS core blockforest )
waLBerla_execute_test( NAME PE_PARMETIS PROCESSES 64 )
endif()
waLBerla_compile_test( NAME PE_PARSEMESSAGE FILES ParseMessage.cpp DEPENDS core )
waLBerla_execute_test( NAME PE_PARSEMESSAGE )
......
//======================================================================================================================
//
// 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 ParMetis.cpp
//! \author Sebastian Eibl <sebastian.eibl@fau.de>
//
//======================================================================================================================
#include "pe/utility/CreateWorld.h"
#include <blockforest/loadbalancing/DynamicParMetis.h>
#include <core/Environment.h>
#include <core/logging/Logging.h>
#include <core/math/Sample.h>
using namespace walberla;
using namespace walberla::pe;
class ReGrid
{
public:
void operator()( std::vector< std::pair< const Block *, uint_t > > & minTargetLevels,
std::vector< const Block * > &, const BlockForest & /*forest*/ )
{
std::for_each( minTargetLevels.begin(),
minTargetLevels.end(),
[](auto& pair){pair.second = pair.first->getLevel() + 1;} );
}
};
class MetisAssignmentFunctor
{
public:
typedef blockforest::DynamicParMetisBlockInfo PhantomBlockWeight;
typedef blockforest::DynamicParMetisBlockInfoPackUnpack PhantomBlockWeightPackUnpackFunctor;
void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & )
{
for( auto it = blockData.begin(); it != blockData.end(); ++it )
{
const auto& corner = it->first->getAABB().maxCorner();
const int weight = int_c( corner[0] + corner[1] + corner[2] );
blockforest::DynamicParMetisBlockInfo info(0);
info.setVertexWeight( weight );
info.setVertexSize( weight );
info.setVertexCoords( it->first->getAABB().center() );
for( uint_t nb = uint_t(0); nb < it->first->getNeighborhoodSize(); ++nb )
{
info.setEdgeWeight(it->first->getNeighborId(nb), int64_c(weight) );
}
it->second = info;
}
}
};
int parmetisTest(const std::string& algorithm,
const std::string& weightsToUse,
const std::string& edgeSource)
{
walberla::MPIManager::instance()->resetMPI();
walberla::MPIManager::instance()->useWorldComm();
WALBERLA_LOG_INFO_ON_ROOT("****** " << algorithm << " | " << weightsToUse << " | " << edgeSource);
// create forest
shared_ptr< BlockForest > forest = createBlockForest( math::AABB(0,0,0,40,40,40),
Vector3<uint_t>(4, 4, 4),
Vector3<bool>(false, false, false),
64,
0);
if (!forest)
{
WALBERLA_LOG_INFO_ON_ROOT( "No BlockForest created ... exiting!");
return EXIT_SUCCESS;
}
forest->setRefreshMinTargetLevelDeterminationFunction( ReGrid() );
auto assFunc = MetisAssignmentFunctor();
forest->setRefreshPhantomBlockDataAssignmentFunction( assFunc );
forest->setRefreshPhantomBlockDataPackFunction( MetisAssignmentFunctor::PhantomBlockWeightPackUnpackFunctor() );
forest->setRefreshPhantomBlockDataUnpackFunction( MetisAssignmentFunctor::PhantomBlockWeightPackUnpackFunctor() );
auto alg = blockforest::DynamicParMetis::stringToAlgorithm( algorithm );